문자열에서 정규식의 모든 항목을 찾는 방법

문자열에서 정규식의 모든 항목을 찾는 방법

POSIX awk와 Gawk에서는 각각 문자열에서 정규식과 일치하는 모든 항목을 어떻게 찾나요?

gsub보다 구체적으로 다음 두 가지 목표 중 하나에 따라 내장 함수로 대체된 모든 항목을 찾습니다.

  • 대상 문자열에서 각 일치 항목의 위치와 길이를 찾고

  • 대상 문자열의 하위 문자열과 일치하는 항목만 찾습니다.

첫 번째 목표를 달성한다는 것은 두 번째 목표를 달성한다는 의미입니다.

  1. POSIX awk에서는

    이러한 목표 중 하나를 달성하는 내장 함수가 있습니까?

    내장 함수는 match가장 왼쪽과 가장 긴 일치 항목만 찾나요?

    match첫 번째 목표를 달성하려면 각 일치 항목을 찾고 대상 문자열에서 일치 항목과 이전 접두사를 제거하여 생성된 대상 문자열의 접미사를 반복적으로 적용하는 것이 올바른 방법입니까? 예 https://gist.github.com/mllamazing/a40946fcf8211a503bed올바른 구현?

  2. 돌팔이에서는,

    array 두 번째 대상의 요구에 따라 호출 후 patsplit(string, array, fieldpat, seps) 일치 항목이 저장 됩니까? 와 사이의 구분자 문자열을 기준으로 array일치하는 위치의 위치를 ​​찾는 것이 가능합니까 ?sepsseps[i]array[i]array[i+1]

감사해요.

답변1

  1. POSIX awk에는
    이러한 목표 중 하나를 달성하는 내장 함수가 있습니까?

아니요. 단일 내장 함수를 사용하지 않고 동일한 효과를 얻을 수 있습니다.

내장 함수는 match가장 왼쪽과 가장 긴 일치 항목만 찾나요?

예. POSIX awk(및 GNU ) awk의 정규식은 항상 탐욕적입니다(즉, 가장 긴 일치 항목이 항상 승리합니다).

match첫 번째 목표를 달성하려면 각 일치 항목을 찾고 대상 문자열에서 일치 항목과 이전 접두사를 제거하여 생성된 대상 문자열의 접미사를 반복적으로 적용하는 것이 올바른 방법입니까?

예, 하지만 gsub()100% 호환성을 원한다면 세부 사항이 꽤 까다롭습니다.

https://gist.github.com/mllamazing/a40946fcf8211a503bed올바른 구현?

대부분의 경우 삭제하면유니버설 서브라인. 문제는 세부 사항에 있습니다. regex빈 문자열이면 코드가 반복됩니다. Classic에서는 awk빈 정규식을 허용하지 않지만 IIRC에서는 nawk허용합니다. 이 문제를 해결하려면 다음을 수행할 수 있습니다.

function FindAllMatches(str, regex, match_arr) {

    ftotal = 0;
    ini = RSTART;
    leng = RLENGTH;

    delete match_arr;

    while (str != "" && match(str, regex) > 0) {
        match_arr[++ftotal] = substr(str, RSTART, RLENGTH)
        str = substr(str, RSTART + (RLENGTH ? RLENGTH : 1))
    }

    RSTART = ini;
    RLENGTH = leng;
}

하지만 100% 호환되지는 않기 gsub()때문에

$ echo 123 | awk '{ gsub("", "-") } 1'
-1-2-3-

위 함수는 일치하는 항목을 3개만 찾습니다(즉, 마지막 일치 항목을 놓칩니다).

다음을 시도해 볼 수 있습니다.

function FindAllMatches(str, regex, match_arr) {

    ftotal = 0;
    ini = RSTART;
    leng = RLENGTH;

    delete match_arr;

    while (match(str, regex) > 0) {
        match_arr[++ftotal] = substr(str, RSTART, RLENGTH)
        if (str == "") break
        str = substr(str, RSTART + (RLENGTH ? RLENGTH : 1))
    }

    RSTART = ini;
    RLENGTH = leng;
}

이렇게 하면 위의 문제가 해결되지만 다른 경우는 중단됩니다. if str = "123"및 function은 끝에 빈 문자열이 있는 regex = "[1-9]*"두 항목을 찾는 반면 while은 하나만 찾습니다 .123gsub()123

지금 당장 찾기에는 너무 게으른 다른 유사한 차이점이 있을 수 있습니다.

  1. 돌팔이에서는,

    array 두 번째 대상의 요구에 따라 호출 후 patsplit(string, array, fieldpat, seps) 일치 항목이 저장 됩니까?

대부분 그렇습니다. 그러나 정규식과 관련된 극단적인 경우는 놀라울 정도로 미묘할 수 있습니다. 이있을 수 있습니다일부위에서 언급한 바와 같이 차이점이 있습니다.

와 사이의 구분자 문자열을 기준으로 array일치하는 위치의 위치를 ​​찾는 것이 가능합니까 ?sepsseps[i]array[i]array[i+1]

예.

관련 정보