2012-12-02 3 views
0

두 개의 둥근 괄호 안의 문자가 처음 나오는 부분을 일치 시키려하지만, 안에있는 부분은 무시하고 싶습니다. 어떤이 있습니까preg_match_all에서 중첩 된 결과를 무시합니다.

$results[0][0] = nested text here 
$results[0][1] = another nested text here 

:

{{some text here {{nested text here}} another text {{another nested text here}} final text}} 

그래서 결과는

some text here {{nested text here}} another text {{another nested text here}} final text 

하지만

preg_match_all("^\{{(.*?)\}}^", $string, $results); 

나에게 브래킷의 첫 번째 쌍 내부의 것들을 제공이 검색해야합니다 이것을 달성하는 방법 preg_match_all?

답변

3

중첩 된 구조는 정규 표현식에 문제를 일으키는 경우가 많습니다 (정규식보다 언어가 더 복잡해지기 때문에). PCRE는 재귀를 지원하기 때문에 일치하는 것을 허용하는 엔진 중 하나입니다. 당신은 결코 당신의 이중 괄호 안의 하나의 중괄호가없는 경우이 패턴을 사용할 수 있습니다 (?R) 다시 자체 내부의 전체 패턴을 둥지

'/\{\{[^{}]*(?:(?R)[^{}]*)*\}\}/' 

.

PCRE가 얼마나 잘 최적화되어 있는지 확신 할 수 없지만 모든 반복을 사용하여 약간의 도움을 줄 수 있습니다. possessive. 즉 모든 연속적인 반복은 상호 배타적이기 때문에, 여기에 필요하지 않습니다 되돌아을 억제 :

'/\{\{[^{}]*+(?:(?R)[^{}]*+)*+ \}\}/' 

당신은 하나의 괄호, 당신은 lookaheads와 비슷한 뭔가를 할 수 있도록 할, 그러나 이것은 이미 정규 표현식이없는 이유를 표시하는 경우 정말 (엔진이 지원하는 경우에도) 중첩 된 구조를 위해 만든 : 그것은 {{ 또는 }} a의 시작을 표시하지 않는

'/\{\{(?:(?!\{\{|\}\}).)*(?:(?R)(?:(?!\{\{|\}\}).)*)*\}\}/' 

지금 대신 비 {} 문자, 우리는 모든 문자의 반복을 할 수 있습니다. 다시 말해, 소유욕을 높이는 것이 좋은 아이디어 일 수 있습니다.

'/\{\{(?:(?!\{\{|\}\}).)*+(?:(?R)(?:(?!\{\{|\}\}).)*+)*+\}\}/' 
+0

멋진 답변! 감사! 그것은 현재 작동합니다. 이 정규 표현은 이해하기가 힘들어 어쩌면 너무 엉망으로 보일 수도 있습니다. 나는 당신의 대답을 분석하기 위해 약간의 시간이 걸릴 것이다. 그러나 첫번째 것이 효과적이다 (그것이 최적의 것이 아닐지라도). – flaviu

+0

@flaviu 소유량 한정 기호에 연결된 튜토리얼은 일반적으로 훌륭한 리소스입니다. 그룹화와 둘러보기도 체크 아웃하면 도움이 될 것입니다. 여기에 [재귀 패턴의 문서] (http://php.net/manual/en/regexp.reference.recursive.php)가 있습니다. –

관련 문제