Perl의 정규 표현식에서 수량자 *, +, ?, {n,m}는 기본적으로 탐욕적 (greedy)입니다: 이는 패턴에 일치하는 최대한 많은 문자를 캡처합니다.
수량자 뒤에 ?를 추가하면 느린 (lazy 또는 non-greedy)으로 바뀌며: 이는 정규 표현식이 일치하는 데 필요한 최소한의 문자를 캡처합니다.
my $str = 'foo <bar> baz <quux>'; $str =~ /<.*>/; # '<bar> baz <quux>'를 캡처합니다.
my $str = 'foo <bar> baz <quux>'; $str =~ /<.*?>/; # '<bar>'를 캡처합니다.
탐욕적 표현식은 HTML 및 기타 중첩 구조를 구문 분석할 때 예상보다 더 많은 내용을 "먹어버릴" 수 있습니다!
<a><b><c>문자열을 구문 분석할 때 다음 두 정규 표현식은 어떻게 다릅니까:/<(.*)>/와/<(.*?)>/?
답변:
/<(.*)>/ (탐욕적)은 최대 블록을 캡처합니다 — 일치: <a><b><c>/<(.*?)>/ (느린)은 첫 번째 그룹만 캡처합니다: <a>예:
my $s = '<a><b><c>'; $s =~ /<(.*)>/; # $1: 'a><b><c' $s =~ /<(.*?)>/; # $1: 'a'
이야기
뉴스 헤드라인을 가져오는 어플리케이션에서 프로그래머는
/\<(.*)\>/를 사용하여<title>뉴스</title>문자열에서 태그 이름을 구문 분석하고자 했습니다. 결과적으로 정규 표현식은 첫 번째<와 마지막>사이의 전체 문자열을 캡처하여 필요한 요소가 아니라 전체를 가져왔습니다. 중첩 태그가 생기자 오류가 발견되었습니다.
이야기
인용된 문자열을 구분하기 위한 논리 구문 분석기에서 사용된 패턴
/"(.*)"/는 예상하지 못하게 첫 번째와 마지막 따옴표 사이의 모든 것을 캡처했습니다. 따라서 마크업이 잘못 분할되었고, 패턴을/"(.*?)"/로 교체할 때까지 문제가 지속되었습니다.
이야기
따옴표를 포함할 수 있는 CSV 자동 파서에서 "탐욕적"으로 잘못된 패턴이 작성되어 여러 열이 하나로 합쳐졌습니다. 도입된 파서의 오류는 대량 데이터에서만 발견되었으며, 느린 패턴 수정이 문제를 해결했습니다.