5

동일한 홀수 결과 (javaScript 및 Flash)를 생성하는 두 가지 언어로 다음 정규 표현식을 사용합니다. 내가 알고 싶은 것은 그것을 고치는 법이 아니라 행동이 일어나고있는 이유는 무엇입니까?Regex는 일치하는 캡처 그룹의 마지막 인스턴스 만 캡처합니다.

정규식 :

\[(\\{2}|\\\]|[^\]])*\] 

여기에서의 목표는이 괄호 문자열과 일치하는, 내가 탈출 브래킷에서 정지하지 않도록합니다.

나는 그것이 정확하게 일치하는 텍스트 입력 [abcdefg]을 가지고 있지만 캡처 그룹의 일부가 나는 abcdefg을 예상대로 g을 그대로 유일한 반환합니다. 표현식을 \[((?:\\{2}|\\\]|[^\]])*)\]으로 변경하면 원하는 결과를 얻습니다.

그렇다면 왜 이런 일이 발생합니까? 다른 언어에서도 일관성이 있습니까?

참고 : 표현식을 \[([^\]])*\]으로 단순화하면 동일한 문제가 발생합니다. 이 같은 캡처 그룹 내부의 * 정량 포함

답변

7

에 관계없이 문제의 액션 스크립트와 자바 스크립트는 항상 그 (또는 상위, 동일한 결과를 산출해야한다, 하지만 정규식의 경우에는 동의하지 않아야합니다.)

그러나 네,이 모든 언어에서 일어나고있는 (또는 오히려 어떤 정규식 맛)됩니다. 그 이유는 당신이 캡쳐 그룹을 반복하고 있기 때문입니다. 더 간단한 예를 들자면 (.)*abc을 맞춰보세요. 그래서 우리가 반복하고있는 것은 (.)입니다. 처음 시도하면 엔진이 그룹에 들어가고 a.이 일치하고 그룹을 나가고 a을 캡처합니다. 한정어가 시작되고 모든 것을 반복합니다. 그래서 우리는 그룹에 다시 들어가서 b과 일치시키고 붙잡습니다. 이 캡처는 이전의 것을 덮어 씁니다. 따라서 \1에는 b이 포함됩니다. 세 번째 반복을 위해 다시 한번 : 캡처는 c으로 덮어 씁니다. 나는 다르게 작동 정규식 맛, 당신은 (대신 그들을 덮어 쓰는) 이전의 모든 캡처에 액세스 할 수있는 단 하나의 모르는

는 .NET이다.

이 해법은 1 p.sw.g. 제안했다. 비 캡쳐 반복에 필요한 그룹화 (캡쳐 및 덮어 쓰기를 모두 수행 할 필요가 없기 때문에 성능이 향상됩니다)를 작성하고 모든 것을 새로운 그룹으로 묶습니다. 귀하의 표현에는 하나의 작은 결함이 있습니다 : 당신은 부정 문자 클래스에 백 슬래시를 포함시키는 것을 포함해야합니다. 그렇지 않으면 역 추적으로 [abc\]에 성냥을 표시 할 수 있습니다. 그래서 여기에 예상대로 작동 식이다 :

\[((?:\\{2}|\\\]|[^\]\\])*)\] 

Working demo. (불행하게도, 그것은 캡처를 표시하지 않습니다, 그러나 그것은 모든 경우에 정확한 일치를 제공 보여줍니다)

참고 귀하를 표현식은 다른 이스케이프 시퀀스를 허용하지 않습니다. 특히 \이라는 단일 문자와 ] 이외의 문자가 있으면 패턴이 실패하게됩니다.이것은 당신이 원하는 무엇을하지 않으면, 당신은 사용할 수 있습니다

\[([^\]\\]*(?:\\.[^\]\\]*)*)\] 

Working demo.

:

\[((?:\\.|[^\]\\])*)\] 

Working demo.

성능이 더 "unrolling-the-loop" 기술로 개선 될 수있다

2

시도 : 그들은 모두 ECMAScript를 구현으로

\[((?:\\{2}|\\\]|[^\]])*)\]