source

정규 표현에서 중첩된 캡처 그룹의 번호는 어떻게 지정됩니까?

factcode 2022. 9. 15. 22:46
반응형

정규 표현에서 중첩된 캡처 그룹의 번호는 어떻게 지정됩니까?

정규 표현에서 네스트된 괄호의 캡처 동작을 처리하는 방법에 대해 정의된 동작이 있습니까?보다 구체적으로, 다른 엔진이 첫 번째 위치에서 바깥쪽 괄호를 캡처하고 이후 위치에서 중첩된 괄호를 캡처할 것으로 예상할 수 있습니까?

다음 PHP 코드를 고려하십시오(PCRE 정규 표현식 사용).

<?php
  $test_string = 'I want to test sub patterns';
  preg_match('{(I (want) (to) test) sub (patterns)}', $test_string, $matches);
  print_r($matches);
?>

Array
(
    [0] => I want to test sub patterns  //entire pattern
    [1] => I want to test           //entire outer parenthesis
    [2] => want             //first inner
    [3] => to               //second inner
    [4] => patterns             //next parentheses set
)

괄호 안의 식 전체가 먼저 캡처되고(테스트하고 싶다), 다음으로 괄호 안의 패턴이 캡처됩니다("want" 및 "to").논리적으로도 일리가 있지만 먼저 하위 괄호를 캡처한 다음 전체 패턴을 캡처하는 경우에도 마찬가지로 논리적인 사례가 작성되는 것을 볼 수 있습니다.

그러면 정규 표현 엔진에서 정의된 동작 전체를 캡처할 것인가, 아니면 패턴의 컨텍스트 및/또는 엔진의 동작에 따라 달라질 것인가(PCRE가 C#과 다른 점, Java가 다른 점 등)?

perlrequick에서

정규식의 그룹화가 중첩되어 있는 경우 $1은 맨 왼쪽의 괄호, $2는 다음 여는 괄호 등을 가진 그룹을 가져옵니다.

주의: 그룹 시작 괄호(?=)는 제외됩니다.

갱신하다

PCRE를 많이 사용하지 않습니다.일반적으로 실제를 사용하고 있기 때문에). 단, PCRE의 문서는 Perl의 문서와 동일합니다.

서브패턴

2.캡처 서브패턴으로서 서브패턴을 설정합니다.은, 하면, 패턴에 「」, 「」, 「」, 「」, 「」를 개입시켜 에게 되돌려지는 것을 합니다.ovector가 됩니다.pcre_exec(). 1부터) 여는 괄호는 왼쪽에서 오른쪽으로(1부터 시작) 카운트되어 캡처 서브패턴의 번호를 가져옵니다.

예를 들어, 문자열 "빨간 왕"이 패턴과 일치할 경우

the ((red|white) (king|queen))

캡처된 서브스트링은 "red king", "red" 및 "king"이며 각각 1, 2, 3의 번호가 매겨집니다.

PCRE가 Perl regex 호환성을 잃고 있는 경우는, 「Perl Cognate Regular Expressions」, 「Perl Comparable Regular Expressions」등의 약어를 재정의할 필요가 있습니다.아니면 그냥 의미 있는 글자를 없애버리거나.

네, 이 모든 것이 관심 있는 모든 언어에 대해 잘 정의되어 있습니다.

  • Java - http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html#cg
    .0으로 하다'
  • .Net - http://msdn.microsoft.com/en-us/library/bs2twtah(VS.71).aspx
    를 사용한 는 첫 가 매겨집니다는 1부터 시작합니다. 캡처, 패턴 라고 말합니다.
  • PHP(PCRE 함수) - http://www.php.net/manual/en/function.preg-replace.php#function.preg-replace.parameters
    "\0 또는 $0은 패턴 전체에 일치하는 텍스트를 나타냅니다.여는 괄호는 왼쪽에서 오른쪽으로 카운트되어(1부터 시작) 캡처 서브패턴의 번호를 취득합니다.(이는 권장되지 않는 POSIX 함수에도 해당됩니다)
  • PCRE - http://www.pcre.org/pcre.txt
    Alan M은 "How pcre_exec() returns capture substrings" 를 사용합니다.

    첫 번째 정수 쌍인 overctor[0]와 overctor[1]는 다음과 같이 식별한다.패턴 전체와 일치하는 제목 문자열의 일부입니다.다음.pair는 첫 번째 캡처 서브패턴에 사용됩니다.pcre_exec()에 의해 반환되는 것은 가장 높은 번호의 페어보다1개 많은 것입니다.설정되었습니다.예를 들어, 2개의 서브스트링이 캡처된 경우,반환되는 값은 3입니다.캡처 서브패턴이 존재하지 않는 경우,성공한 일치의 값은 1로, 첫 번째 쌍만오프셋이 설정되었습니다.
    
  • Perl의 차이점 - http://perldoc.perl.org/perlre.html#Capture-buffers
    $1, $2 등은 예상대로 캡처 그룹과 일치합니다(예: 괄호 열기). 단, $0은 쿼리 문자열 전체가 아닌 프로그램 이름을 반환하고 $&를 대신 사용합니다.

다른 언어(Python, Ruby 등)에서도 비슷한 결과를 얻을 수 있습니다.

내부 캡처 그룹을 먼저 나열하는 것이 논리적으로 타당하다고 말씀하셨는데, 이는 단순히 닫았을 때 인덱스를 작성하는 문제일 뿐, 여는 것이 아닙니다.(제 말이 맞다면)그러나 이렇게 하는 것은 자연스럽지 않기 때문에(예를 들어 읽기 방향 규약을 따르지 않음), 인스펙션으로 어떤 캡처 그룹이 특정 결과 인덱스에 있는지 결정하는 것이 더 어려워집니다(아마도 유의하지 않을 수 있음).

매치 문자열 전체를 위치 0에 두는 것도 의미가 있습니다.대부분의 일관성을 위해서입니다.regex에서 regex까지의 캡처 그룹의 수와 실제로 일치하는 캡처 그룹의 수에 관계없이 일치하는 문자열 전체를 동일한 인덱스에 유지할 수 있습니다(예를 들어 Java는 각 캡처 그룹의 일치된 그룹 배열 길이가 컨텐츠와 일치하지 않습니다).예를 들면, 「a(.*) pattern」입니다.항상 capture_group_results[capting_group_results_length - 2]를 검사할 수 있지만, Perl은 변수 ($1, $2 등)를 동적으로 작성하는 Perl 언어로는 잘 번역되지 않습니다(Perl은 일치하는 식에 $&를 사용하기 때문에 물론 나쁜 예입니다).

내가 알고 있는 모든 regex 플레이버는 첫 번째 괄호가 표시된 순서대로 그룹화됩니다.외부 그룹은 포함된 하위 그룹 앞에 번호가 매겨지는 것은 명시적 정책이 아니라 자연스러운 결과입니다.

그게 흥미로운 건 이름 있는 그룹들이야.대부분의 경우 패런의 상대적인 위치에 따라 번호를 매기는 동일한 정책을 따릅니다.이름은 번호의 에일리어스일 뿐입니다.단, 에서는.NET 정규식에 이름 있는 그룹은 번호가 매겨진 그룹과 별도로 번호가 매겨집니다.예를 들어 다음과 같습니다.

Regex.Replace(@"one two three four", 
              @"(?<one>\w+) (\w+) (?<three>\w+) (\w+)",
              @"$1 $2 $3 $4")

// result: "two four one three"

실제로는 번호이름의 별칭입니다.이름 있는 그룹에 할당된 번호는 "실제" 번호 그룹이 끝나는 곳에서 시작합니다.기괴한 정책처럼 보일지 모르지만 그럴 만한 이유가 있습니다. 바로 '에서'입니다.NET 정규식은 동일한 그룹 이름을 정규식에 두 번 이상 사용할 수 있습니다.이것에 의해, 다른 로케일의 부동 소수점 번호의 매칭에 대해서, 이 스레드의 것과 같은 정규식이 가능하게 됩니다.

^[+-]?[0-9]{1,3}
(?:
    (?:(?<thousand>\,)[0-9]{3})*
    (?:(?<decimal>\.)[0-9]{2})?
|
    (?:(?<thousand>\.)[0-9]{3})*
    (?:(?<decimal>\,)[0-9]{2})?
|
    [0-9]*
    (?:(?<decimal>[\.\,])[0-9]{2})?
)$

수천 개의 분리기가 있으면 정규식의 어느 부분이 일치하든 간에 "천 개" 그룹에 저장됩니다.마찬가지로 소수 구분 기호(있는 경우)는 항상 "decimal" 그룹에 저장됩니다.물론 재사용 가능한 이름 있는 그룹을 사용하지 않고 구분자를 식별하고 추출하는 방법도 있지만, 이 방법이 훨씬 편리하기 때문에 이상한 번호 체계를 정당화하는 것 이상이라고 생각합니다.

또, Perl 5.10+도 있습니다.이것에 의해, 그룹 캡쳐에 대해서, 내가 무엇을 할지를 모르는 것보다 더 많은 컨트롤이 가능하게 됩니다. : D

왼쪽 paren 순으로 캡처하는 순서는 지금까지 작업한 모든 플랫폼에서 표준입니다(perl, php, ruby, egrep).

언급URL : https://stackoverflow.com/questions/1313934/how-are-nested-capturing-groups-numbered-in-regular-expressions

반응형