정규식에서 중첩 된 캡처 그룹은 어떻게 번호가 매겨 집니까?
정규식이 중첩 된 괄호의 캡처 동작을 처리하는 방법에 대한 정의 된 동작이 있습니까? 더 구체적으로 말하면, 다른 엔진이 첫 번째 위치에서 바깥 쪽 괄호를 캡처하고 후속 위치에서 중첩 된 괄호를 캡처 할 것이라고 합리적으로 예상 할 수 있습니까?
다음 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과 동일하게 표시됩니다.
SUBPATTERNS
2.
서브 패턴을 캡처 서브 패턴으로 설정합니다. 이는 전체 패턴이 일치 할 때 하위 패턴과 일치하는 주제 문자열의 해당 부분이의ovector
인수를 통해 호출자에게 다시 전달됨을 의미합니다pcre_exec()
. 여는 괄호는 왼쪽에서 오른쪽 (1부터 시작)으로 계산되어 캡처하는 하위 패턴의 수를 얻습니다.예를 들어 문자열 "the red king"이 패턴과 일치하는 경우
the ((red|white) (king|queen))
캡처 된 하위 문자열은 "red king", "red"및 "king"이며 각각 1, 2 및 3으로 번호가 지정됩니다.
PCRE가 Perl 정규식 호환성에서 벗어나면 약어를 다시 정의해야합니다. "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부터 시작하여 자동으로 번호가 매겨집니다. capture, capture element number zero, is the text matched by the whole regular expression pattern. ") - 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 ()가 캡처 된 하위 문자열을 반환하는 방법"을 검색하고 다음 다섯 번째 단락을 읽으십시오.첫 번째 정수 쌍인 ovector [0] 및 ovector [1]은 다음을 식별합니다. 전체 패턴과 일치하는 제목 문자열의 일부입니다. 다음 쌍은 첫 번째 캡처 하위 패턴 등에 사용됩니다. 가치 pcre_exec ()에 의해 반환되는 것은 설정되었습니다. 예를 들어 두 개의 하위 문자열이 캡처 된 경우 반환 된 값은 3입니다. 캡처하는 하위 패턴이없는 경우 성공적인 일치의 값은 1이며 첫 번째 쌍만 오프셋 수가 설정되었습니다.
- 펄의 다른 - http://perldoc.perl.org/perlre.html#Capture-buffers
$ 1, $ 2 등 예상대로 그룹을 캡처 일치 (예 : 여는 괄호의 발생에 의해), 그러나 $ 0을 반환 프로그램 이름이 아닌 전체 쿼리 문자열-대신 $ &를 사용합니다.
다른 언어 (Python, Ruby 등)에서도 유사한 결과를 찾을 수 있습니다.
You say that it's equally logical to list the inner capture groups first and you're right - it's just be a matter of indexing on closing, rather than opening, parens. (if I understand you correctly). Doing this is less natural though (for example it doesn't follow reading direction convention) and so makes it more difficult (probably not significantly) to determine, by insepection, which capturing group will be at a given result index.
Putting the entire match string being in position 0 also makes sense - mostly for consistency. It allows the entire matched string to remain at the same index regardless of the number capturing groups from regex to regex and regardless of the number of capturing groups that actually match anything (Java for example will collapse the length of the matched groups array for each capturing group does not match any content (think for example something like "a (.*)pattern"). You could always inspect capturing_group_results[capturing_group_results_length - 2], but that doesn't translate well to languages to Perl which dynamically create variables ($1, $2 etc.) (Perl's a bad example of course, since it uses $& for the matched expression, but you get the idea :).
Every regex flavor I know numbers groups by the order in which the opening parentheses appear. That outer groups are numbered before their contained sub-groups is just a natural outcome, not explicit policy.
Where it gets interesting is with named groups. In most cases, they follow the same policy of numbering by the relative positions of the parens--the name is merely an alias for the number. However, in .NET regexes the named groups are numbered separately from numbered groups. For example:
Regex.Replace(@"one two three four",
@"(?<one>\w+) (\w+) (?<three>\w+) (\w+)",
@"$1 $2 $3 $4")
// result: "two four one three"
In effect, the number is an alias for the name; the numbers assigned to named groups start where the "real" numbered groups leave off. That may seem like a bizarre policy, but there's a good reason for it: in .NET regexes you can use the same group name more than once in a regex. That makes possible regexes like the one from this thread for matching floating-point numbers from different locales:
^[+-]?[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})?
)$
If there's a thousands separator, it will be saved in group "thousand" no matter which part of the regex matched it. Similarly, the decimal separator (if there is one) will always be saved in group "decimal". Of course, there are ways to identify and extract the separators without reusable named groups, but this way is so much more convenient, I think it more than justifies the weird numbering scheme.
And then there's Perl 5.10+, which gives us more control over capturing groups than I know what to do with. :D
The order of capturing in the order of the left paren is standard across all the platforms I've worked in. (perl, php, ruby, egrep)
'program story' 카테고리의 다른 글
OpenCV의 cvWaitKey () 함수는 무엇을합니까? (0) | 2020.10.23 |
---|---|
SQL에서 Entity Framework 수 그룹화 기준 (0) | 2020.10.23 |
가상 디렉터리를 추가 할 때 "경로 (C : \ inetpub \ wwwroot)에 대한 액세스를 확인할 수 없습니다." (0) | 2020.10.22 |
Git & Intellij, 변경된 파일의 일부만 커밋하는 방법 (0) | 2020.10.22 |
onConnected 함수가 호출 된 후 GoogleApiClient에서 "GoogleApiClient가 아직 연결되지 않았습니다"라는 메시지가 표시됨 (0) | 2020.10.22 |