2012-03-01 3 views
1

중첩 된 문자열을 구문 분석하거나 HTML을 실제 파서로 처리하는 것이 더 좋지만 제 경우에는 간단한 템플릿이 있고 Wiki의 제목 내용을 추출하고 싶습니다. 템플릿에서 'title'매개 변수 이 문제를 해결하는 데는 시간이 걸렸지 만, Lars Olav Torvik (http://regex.larsolavtorvik.com/)의 정규식 도구 덕분에이 사용자 포럼은 여기에 있습니다. 누군가 유용 할 수 있습니다. (우리 모두는 기여하기를 원합니다, 그는 그렇지 않습니까?) 코멘트로 주석 된 다음 코드는 트릭을 수행합니다. 그 중 하나에 제목이 없으면 두 개의 템플릿을 함께 사용하지 않기 위해 어설 션을 둘러 봐야했습니다.균형 잡힌 중첩 된 wiki 템플릿을 구문 분석하고 정규식을 사용하여 단일 행 매개 변수의 내용 추출

정규식 주석의 두 가지 질문에 대해 아직 확신하지 않습니다. (?R)에서 재귀 부분을 이해하면 (?# Questions: …)을 참조하십시오. 그것은 가장 바깥에 정의 된 수준, 즉 두 번째 정규식 줄 \{\{과 마지막 정규식 줄 \}\}에서 확인할 내용을 가져옵니다. 그것이 맞을까요? (?R) 부스의 대안이 똑같이 작동하기 전에 +++의 차이점은 무엇입니까?

  1. (가장 간단한) 페이지에 origninal 위키 템플릿 :

    $wikiTemplate = " 
    {{Templ1 
    | title = (1. template) title 
    }} 
    
    {{Templ2 
    | any parameter = something {{template}} 
    }} 
    
    {{Templ1 
    | title = (3. template) title 
    }} 
    "; 
    
  2. 교체 :

    $wikiTemplate = preg_replace(
        array(
        // tag all templates with START … END and add a TITLE-placeholder before 
        // and take care of balanced {{ … }} recursiveness 
        "@(?s) (?# switch to dotall match, i.e. also linebreaks) 
         \{\{ (?# find two {{) 
         (?: (?# group 1 as a non-backreferenced match ) 
         (?: (?# group 2 as a non-backreferenced match ) 
          (?! (?# in group 1 anything but not {{ or }}) 
          \{\{ 
          | (?# or) 
          \}\} 
         ) 
          . 
         )++ (?# Question: what is the differenc between ++ and + here?) 
         | (?# or) 
         (?R) (?# is it recursive of what is defined in the outermost, 
           i.e. 2nd regexp line with \{\{ and last line with \}\} 
           Question: is that here understood correctly?) 
        ) 
         * (?# zero or many times of the inner regexp defintions) 
         \}\} (?# find two }}) 
        @x",// x-extended → ignore white space in the pattern 
        // replace TITLE by single line content of title parameter 
        "@ 
         (?<=TITLE) (?# TITLE must preceed the following linebreak but is not 
            backreferenced within \\0, i.e. the whole returned match) 
         ([\n\r]+) (?#linebr in 1 may also described as . because of 
            s-modifier dotall) 
         (?:  (?# start non-backreferenced match) 
         .  (?# any character but not followed by START) 
         (?!START) 
        )+  (?# multiple times) 
         (?:  (?# start non-backreferenced match) 
         \|\s*title\s*=\s* (?#find the parameter '| title = ') 
        ) 
         ([^\r\n]+) (?#get title now to \\2 but exclude the line break. 
            Note it is buggy when there is no line break) 
         (?:  (?# start non-backreferenced match) 
         .  (?# any character but not followed by END) 
         (?!END) 
        ) 
         +  (?# multiple times) 
         .  (?# any single character, e.g. the last because as all 
           stuff before captures anything not followed by END) 
         (?:END) (?#a not backreferenced END) 
        @msx", // m-multiline, s-dotall match also linebreaks, 
          // x-extended → ignore white space in the pattern 
    ), 
        array(
        "TITLE\nSTART\\0END", // \0 is the whole returned match, i.e. the template 
        # replace the TITLE to TITLEtitle contentTITLE… 
        "\\2TITLE\\0", 
    ), 
        $wikiTemplate 
    ); 
    print_r($wikiTemplate); 
    
  3. 출력은 제목 태그 제목으로 다음이다 제목이있는 경우에만 각 템플릿 위 :

    ,363,210 내 정규 표현식 이해에 대한 질문, 또는 개선을위한
    TITLE(1. template) titleTITLE 
    START{{Templ1 
    | title = (1. template) title 
    }}END 
    
    TITLE 
    START{{Templ2 
    | any parameter = something {{template}} 
    }}END 
    
    TITLE(3. template) titleTITLE 
    START{{Templ1 
    | title = (3. template) title 
    }}END 
    

모든 내부? 감사합니다. Andreas.

답변

0

++은 소유량 한정어입니다. 반복 한정 기호 (+, *, {...})에 +을 추가하면 소유욕이 생깁니다. 즉, 처음으로 반복을 떠나면 정규식 엔진이 더 이상 반복하지 않고 다시 시도하지 않습니다. 그래서 그들은 기본적으로 반복을 원자 집단으로 만듭니다. 때로는 최적화이며 때로는 실제로 차이를 만듭니다. 아주 좋은 일을 할 수 있습니다 reading here.

그리고 두 번째 질문에 대한

(?R) 단순히 다시 전체 패턴과 일치하는 것을 시도 할 것이다. 이를 위해 PCRE의 PHP 문서에서 찾을 수있는 good article이 있습니다.

기타 문의 사항은 더 궁금한 부분이 Code Review 일 수 있습니다.

+0

오직이 질문이 얼마나 오래되었는지 깨닫습니다 ... –

+0

어쨌든 고맙습니다 .--) 질문의 길이는 중요하지 않습니다. –