2017-12-12 24 views
3

나는 여전히 펄을 배우기 때문에 분명한 질문입니다. 괄호로 묶지 않은 텍스트를 찾는 방법이 있습니까? 예를 들어 foo를 검색하면 두 번째 줄만 일치합니다. ("일치 찾을 때까지 문자를 스킵")일치하는 텍스트가 괄호로 묶이지 않음

(bar foo bar) 
bar foo (
bar foo 
    (bar) (foo) 
) 
+0

부정적 예측을 사용하고 있습니까? – Boschko

답변

4

이것은 "명백한"것은 아닙니다. 반대로. 복잡한 패턴에 대해 "일치하지 않는다"라고 말하는 직접적인 방법은 없습니다 (문자 수준에서 좋은 지원이 있습니다, [^a], \S 등). 정규 표현식은 먼저 일치하는 것에 관한 것이지 일치하지 않는 것에 관한 것이 아닙니다.

하나의 방법은 해당 중첩 된 구분 기호를 일치시키고 그 이외의 모든 것을 얻는 것입니다.

중첩 된 구분 기호를 찾는 좋은 도구는 핵심 모듈 Text::Balanced입니다. 일치하는 부분은 일치하기 전의 부분 문자열과 일치 이후의 부분 문자열을 제공 할 수 있습니다.

use warnings; 
use strict; 
use feature 'say'; 

use Text::Balanced qw(extract_bracketed); 

my $text = <<'END'; 
(bar foo bar) 
bar foo (
bar foo 
    (bar) (foo) 
    ) 
END 

my ($match, $before); 
my $remainder = $text; 
while (1) { 
    ($match, $remainder, $before) = extract_bracketed($remainder, '(', '[^(]*'); 
    print $before // $remainder; 
    last if not defined $match; 
} 

extract_bracketed 반환 경기, 경기 전에 하위 문자열 나머지 ($remainder) 및 하위 문자열 ($before); 그래서 우리는 나머지 부분에서 일치를 유지합니다.

취한 this post 여기에는 더 자세한 정보와 다른 방법이 있으며 Regexp::Common을 사용합니다.

+0

이 모듈에 대해 알지 못했습니다. 감사! 그러나'$ text' 또는'$ lead' 내부에서 일치 할 때 줄 번호를 찾는 것이 어렵다는 것을 알고 있습니다. 한가지 방법은'$ match'에서 개행 문자의 수를 세는 것입니다. 그러나 더 좋은 방법이 있습니까? – Tohiko

+1

@Tohiko 환영합니다. 근원에있는 숯/선이 무엇인지 발견하고 싶습니까? '$ lead' (또는'$ text', 그것이 고갈됨에 따라)에서'\ n'을 세기는 것은 소스에있는 행을 알려주지 않습니다. 나는 그것을 들여다 볼 것이다. – zdim

+0

@Tohiko'$ lead'를'$ before'로,'$ text'를'$ remainder'로 변경했음을 참고하십시오. – zdim

5

정규식 패턴 암시 최고의 \G(?s:.)*? 있습니다. 다음은 중첩 된 괄호를 건너 뛸 문자로 간주하기 위해 해당 정의를 확장합니다.

while (
    $string =~ m{ 
     \G (?&MEGA_DOT)*? 

     (foo) 

     (?(DEFINE) 
     (?<MEGA_DOT> [^()] | \((?&MEGA_DOT)*+ \)) 
    ) 
    }xg 
) { 
    say "Found a match at pos $-[1]."; 
} 
+0

훌륭함! 하지만 이것이 사람들이 Perl을 냄새를 맡을 때 두려워하는 이유라고 생각합니다. ;;-) – PerlDuck

+1

@ PerlDuck, 사실, Perl이 얼마나 간단하고 구조화 된 것인지 놀랍습니다. – ikegami

+0

초급자로서 나는 이것을 이해할 수 없으므로 배울 수있는 상세한 방법론을 친절하게 제공하십시오. – ssr1012