2013-08-20 2 views
3

this answer에 대한 몇 가지 테스트를 실행하는 동안 다음과 같은 예기치 않은 동작이 나타났습니다. 이 첫 번째 후 <tag>의 모든 항목을 제거합니다 :역 참조는 참조하는 그룹을 뒤따라야합니까?

var input = "<text><text>extra<words><text><words><something>"; 
Regex.Replace(input, @"(<[^>]+>)(?<=\1.*\1)", ""); 
// <text>extra<words><something> 

하지만이되지 않습니다 마찬가지로

Regex.Replace(input, @"(?<=\1.*)(<[^>]+>)", ""); 
// <text><text>extra<words><text><words><something> 

는, 이번이 마지막 이전 <tag>의 모든 발행 수를 제거합니다 :

Regex.Replace(input, @"(<[^>]+>)(?=.*\1)", ""); 
// extra<text><words><something> 

하지만 그렇지 않습니다.

Regex.Replace(input, @"(?=\1.*\1)(<[^>]+>)", ""); 
// <text><text>extra<words><text><words><something> 

그래서이 생각이 나게 & hellip;

.NET 정규 표현식 엔진에서 참조하는 그룹 이후에 역 참조가 이어야합니까? 아니면 작동하지 않는 패턴이 계속 진행되고 있습니까?

+0

논리적으로 말하자면, 먼저 뭔가를 캡처 한 다음 역 참조로 사용해야합니다. 그렇지 않으면 재귀 적 정규식 [this like this] (http://stackoverflow.com/questions/18262551/can-the-for-loop-be- PHP 코드 조각/18262967 # 18262967)이 실패합니다 :) PS : 그것은 넷뿐 아니라 모든 유형의 사례라고 생각합니다. 데모보기 [php pcre] (http://regex101.com/r/zR9jR2) – HamZa

+1

@HamZa 감사합니다. 좋은 지적입니다. lookaround assertions *는 다른 것으로 생각했을 것입니다. 왜냐하면 (이해할 때) 문자열의 일치하는 섹션 다음에 평가되어야하기 때문입니다. 즉, 어설 션을 검사하기 전에 ''을 찾아야합니다. 그러나 정규 표현식의 내부에 대해 너무 많이 알지는 않습니다. 그래서 나는 틀릴 수도 있습니다.또한, 대부분의 경우 엔진의 동작이 패턴에 나타난 순서보다는 평가 된 순서에 의존하면 더 놀랄 것입니다. –

답변

3

당신의 질문도 저도 생각했습니다. 그래서 RegexBuddy과 약간의 테스트를 실행했고 놀랍게도 실제로 작동하지 않는다고 말한 두 번째 정규식 (?<=\1.*)(<[^>]+>)과 다른 사람들은 정확히 당신이 말한 것처럼 작동했습니다. 그런 다음 동일한 표현식 - 두 번째 코드 -을 C# 코드로 시도했지만 실제로 발생하지 않았습니다.

이것은 나 혼란 스러웠다. 그런 다음 RegexBuddy 버전이 2008 년으로 거슬러 올라가서. NET 엔진이 작동하는 방식에 변화가 있었음에 틀림 없다.하지만이 사실은 합리적이지만 사실에 비추어졌다. 2008 년 이전의 lookbehind는 나머지 표현식이 일치 한 후에 평가되었습니다. 나는이 행동이 lookbehinds에서 약간 받아 들일 수 있다고 느꼈습니다. 그 전에 뭔가를 뒤에서 찾기 전에 뭔가 일치해야하기 때문입니다. 당신으로

(?<=(\w))\1 

:

그럼에도 불구하고, 엔진은 요즘은 그들을 발견하고 나는 사건의 반대 상황처럼 다음 식을 사용하여이를 발견 할 수있을 때 lookarounds을 평가하는 것 내가 정규식 안에 단어 문자를 캡처하고 그것을 외부 참조 그것을 볼 수 있습니다. 이 문자열을 hello 문자열로 테스트하고 두 번째 l 문자가 예상대로 일치 했으므로 식의 나머지 부분과 일치하기 전에 lookbehind가 실행 되었음이 증명되었습니다.

결론 : 예, 역 참조는 참조하는 그룹 다음에 나타나야합니다. 그렇지 않으면 일치하는 의미 체계가 없습니다.

+1

'(? <= \ 1) \ w'은 존재하지 않는 캡처 그룹에 대한 참조를 포함하고 있기 때문에 잘못된 구문입니다. '(? <= \ 1) (\ w)'은 유효한 문법이지만 그룹이 일치에 참여하기 전에 그룹의 내용과 일치하기 때문에 성공하지 못합니다. –

+0

@ AlanMoore 물론 당신은 실수를 바로 잡았습니다. 고맙습니다. –

+0

응답 시간을내어 주셔서 감사합니다. 그룹 전에 나타나면 실제로 예외가 없습니다. 그것은 단지 아무것도 일치하지 않습니다. 참조하는 그룹이 아직 캡처되지 않은 경우 역 참조가 빈 문자열과 일치한다고 생각했지만 실제로는 아무것도 일치하지 않습니다. 'Regex.Matches ("hello", @ "(?! 1)()")'는 길이가 0 인 문자열과 일치합니다. 모든 문자 주위에. –