Regular Expressions
욕심 많은 및 게으른 한정 기호
수색…
매개 변수
한정 기호 | 기술 |
---|---|
? | 앞의 문자 또는 하위 표현식을 0 번 또는 1 번 (바람직하게는 1)과 일치시킵니다. |
* | 앞의 문자 또는 하위 표현식을 0 번 이상 (가능한 한 많이) 찾습니다. |
+ | 앞의 문자 또는 하위 표현식을 1 번 이상 (가능한 한 많이) 찾습니다. |
{n} | 앞의 문자 또는 하위 표현식을 정확하게 n 번 매치하십시오. |
{min,} | 앞의 문자 또는 부분 표현식을 최소 또는 여러 번 (가능한 한 많이) 찾습니다. |
{0,max} | 앞의 문자 또는 하위 표현식을 최대 또는 최소 횟수만큼 일치시킵니다 (가능한 한 최대에 가깝습니다). |
{min,max} | 앞의 문자 또는 부분 표현식을 최소한 min 시간에서 max 시간 (가능한 한 최대 값에 가깝게)만큼 일치시킵니다. |
게으른 한정어 | 기술 |
?? | 앞의 문자 또는 하위 표현식을 0 번 또는 1 번 (바람직하게는 0)과 일치시킵니다. |
*? | 앞의 문자 또는 하위 표현식을 0 번 이상 일치시킵니다 (가능한 한 적게). |
+? | 앞의 문자 또는 하위 표현식을 1 회 이상 일치시킵니다 (가능한 한 적게). |
{n}? | 앞의 문자 또는 하위 표현식을 정확하게 n 번 매치하십시오. 욕심 많은 버전과 게으른 버전 사이에는 차이가 없습니다. |
{min,}? | 앞의 문자 또는 부분 표현식을 min 이상 반복하십시오 (가능한 min에 가깝게). |
{0,max}? | 앞의 문자 또는 하위 표현식을 최대 또는 최소 횟수만큼 일치시킵니다 (가능한 한 적게). |
{min,max}? | 앞의 문자 또는 부분 표현식을 최소한 min 시간에서 max 시간 (가능한 한 min에 가깝게)과 일치시킵니다. |
비고
탐욕
욕심쟁이 한정 기호는 항상 역 추적으로 짧은 일치를 탐색하기 전에 가능한 한 여러 번 하위 패턴을 반복하려고합니다.
일반적으로 욕심 패턴은 가능한 가장 긴 문자열과 일치합니다.
기본적으로 모든 한정 기호는 욕심이 있습니다.
게으름
게으른 ( non-greedy 또는 reluctant 라고도 함) 수량 지정자는 항상 확장을 통해 더 긴 일치를 탐색하기 전에 하위 패턴을되도록 적게 몇 번 반복하려고 시도합니다.
일반적으로 게으른 패턴은 가능한 가장 짧은 문자열과 일치합니다.
한정 기호를 게으르게 만들려면 그냥 붙이 ?
기존의 수량 화기 (예 : +?
, {0,5}?
.
욕심과 게으름의 개념은 역 추적 엔진에만 존재합니다.
greedy / lazy 한정 기호의 개념은 역 추적 정규식 엔진에만 존재합니다. 역 추적을하지 않는 regex 엔진이나 POSIX 호환 regex 엔진에서 한정사는 일치를 찾는 방법을 지정하지 않고 반복의 상한과 하한 만 지정합니다. 이러한 엔진은 항상 가장 왼쪽의 가장 긴 문자열과 일치합니다.
게으름 대 게으름
주어진 다음과 같은 입력 :
aaaaaAlazyZgreeedyAlaaazyZaaaaa
하나의 욕심 : 우리는이 패턴을 사용합니다 A.*Z
, 하나 게으른 : A.*?Z
. 이러한 패턴은 다음과 일치합니다.
-
A.*Z
1 개의 일치 항목을 생성합니다 :AlazyZgreeedyAlaaazyZ
(예 : Regex101 , Rubular ) -
A.*?Z
AlazyZ
와AlaaazyZ
(예 : Regex101 , Rubular )와 일치하는 2 개의 결과를 산출A.*?Z
우선 A.*Z
일에 중점을 둡니다. 첫 번째 A
와 일치 할 때, .*
.는 욕심이 많고, 그 다음 많은 것을 일치 시키려고합니다 .
가능한 한.
aaaaaAlazyZgreeedyAlaaazyZaaaaa
\________________________/
A.* matched, Z can't match
Z
가 일치하지 않으므로 엔진이 백 트랙하고 .*
는 하나 더 적게 일치해야합니다 .
:
aaaaaAlazyZgreeedyAlaaazyZaaaaa
\_______________________/
A.* matched, Z can't match
이것은 마침내 이것에 올 때까지, 몇 번 더 발생합니다 :
aaaaaAlazyZgreeedyAlaaazyZaaaaa
\__________________/
A.* matched, Z can now match
이제 Z
가 일치 할 수 있으므로 전체 패턴이 일치합니다.
aaaaaAlazyZgreeedyAlaaazyZaaaaa
\___________________/
A.*Z matched
반대로 A.*?Z
의 꺼리는 (게으른) 반복은 처음에는 거의 일치하지 않습니다 .
가능한 한 많이 복용 한 다음 복용하십시오 .
필요에 따라 이것은 입력에서 두 개의 일치 항목을 찾은 이유를 설명합니다.
다음은 두 패턴이 일치하는 것을 시각적으로 나타낸 것입니다.
aaaaaAlazyZgreeedyAlaaazyZaaaaa
\____/l \______/l l = lazy
\_________g_________/ g = greedy
polygenelubricants에 의해 만들어진 답을 바탕으로 한 예.
POSIX 표준에는 ?
연산자, 그래서 많은 POSIX 정규식 엔진 은 게으른 일치 하지 않습니다 . 리팩토링, 특히 "최고의 트릭" 으로 인해 어떤 경우에는 일치하는 데 도움이 될 수 있지만 진정한 게으른 일치를 얻는 유일한 방법은이를 지원하는 엔진을 사용하는 것입니다.
여러 일치가있는 경계
잘 정의 된 경계를 가진 입력이 있고 문자열에서 둘 이상의 일치를 예상하는 경우 두 가지 옵션이 있습니다.
- lazy quantifiers 사용하기.
- 부정 문자 클래스 사용.
다음을 고려하세요:
당신은 간단한 템플릿 엔진을 가지고 있는데, $[foo]
와 같은 부분 문자열을 대체하기를 원할 것입니다 $[foo]
여기서 foo
는 임의의 문자열이 될 수 있습니다. 이 부분 문자열을 []
사이의 부분을 기반으로하는 것으로 대체하려고합니다.
\$\[(.*)\]
과 같은 것을 시도한 다음 첫 번째 캡처 그룹을 사용할 수 있습니다.
이 문제는 something $[foo] lalala $[bar] something else
같은 문자열이 있으면 일치하는 것입니다.
something $[foo] lalala $[bar] something else
| \______CG1______/|
\_______Match______/
캡처 그룹은 foo] lalala $[bar
유효하거나 유효하지 않을 수있는 foo] lalala $[bar
.
두 가지 해결책이 있습니다.
게으름 사용하기 :이 경우
*
게으름을 만드는 것은 올바른 것을 찾는 것에 대한 하나의 방법입니다. 그래서 표현식을\$\[(.*?)\]
부정 문자 클래스 사용 :
[^\]]
식을\$\[([^\]]*)\]
합니다.
두 솔루션 모두 결과는 동일합니다.
something $[foo] lalala $[bar] something else
| \_/| | \_/|
\____/ \____/
캡쳐 그룹은 각각 foo
와 bar
입니다.
무효화 된 문자 클래스를 사용하면 역 추적 문제가 줄어들고 큰 입력에 대해 CPU에 많은 시간을 절약 할 수 있습니다.