비 캡처 그룹(예: (?:)
)은 정규식에서 어떻게 사용되며 어떤 용도로 사용됩니까?
질문자 :never_had_a_name
이것을 예를 들어 설명하려고 합니다.
다음 텍스트를 고려하십시오.
http://stackoverflow.com/ https://stackoverflow.com/questions/tagged/regex
이제 아래 정규식을 적용하면 ...
(https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?
... 나는 다음과 같은 결과를 얻을 것입니다 :
Match "http://stackoverflow.com/" Group 1: "http" Group 2: "stackoverflow.com" Group 3: "/" Match "https://stackoverflow.com/questions/tagged/regex" Group 1: "https" Group 2: "stackoverflow.com" Group 3: "/questions/tagged/regex"
하지만 프로토콜은 신경쓰지 않고 URL의 호스트와 경로만 원합니다. (?:)
을 포함하도록 정규식을 변경합니다.
(?:https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?
이제 내 결과는 다음과 같습니다.
Match "http://stackoverflow.com/" Group 1: "stackoverflow.com" Group 2: "/" Match "https://stackoverflow.com/questions/tagged/regex" Group 1: "stackoverflow.com" Group 2: "/questions/tagged/regex"
보다? 첫 번째 그룹은 캡처되지 않았습니다. 파서는 그것을 사용하여 텍스트를 일치시키지만 나중에 최종 결과에서 무시합니다.
편집하다:
요청에 따라 그룹에 대해서도 설명하겠습니다.
글쎄, 그룹은 많은 목적을 수행합니다. 더 큰 일치 항목(이름 지정 가능)에서 정확한 정보를 추출하는 데 도움이 될 수 있으며 이전 일치 그룹과 다시 일치시킬 수 있으며 교체에 사용할 수 있습니다. 몇 가지 예를 들어 볼까요?
어떤 종류의 XML 또는 HTML이 있다고 상상해 보십시오( 정규식이 작업에 가장 적합한 도구가 아닐 수도 있지만 예를 들어 보기에는 좋습니다). 태그를 구문 분석하고 싶기 때문에 다음과 같이 할 수 있습니다(이해하기 쉽도록 공백을 추가했습니다).
\<(?<TAG>.+?)\> [^<]*? \</\k<TAG>\> or \<(.+?)\> [^<]*? \</\1\>
첫 번째 정규식에는 명명된 그룹(TAG)이 있고 두 번째 정규식은 공통 그룹을 사용합니다. 두 정규식은 동일한 작업을 수행합니다. 첫 번째 그룹의 값(태그 이름)을 사용하여 닫는 태그와 일치시킵니다. 차이점은 첫 번째 항목은 이름을 사용하여 값과 일치하고 두 번째 항목은 그룹 인덱스(1부터 시작)를 사용한다는 것입니다.
이제 몇 가지 대체를 시도해 보겠습니다. 다음 텍스트를 고려하십시오.
Lorem ipsum dolor sit amet consectetuer feugiat fames malesuada pretium egestas.
이제 이 멍청한 정규식을 사용해 보겠습니다.
\b(\S)(\S)(\S)(\S*)\b
이 정규식은 3자 이상의 단어와 일치하고 그룹을 사용하여 처음 세 글자를 구분합니다. 결과는 다음과 같습니다.
Match "Lorem" Group 1: "L" Group 2: "o" Group 3: "r" Group 4: "em" Match "ipsum" Group 1: "i" Group 2: "p" Group 3: "s" Group 4: "um" ... Match "consectetuer" Group 1: "c" Group 2: "o" Group 3: "n" Group 4: "sectetuer" ...
따라서 대체 문자열을 적용하면:
$1_$3$2_$4
... 그 위에 첫 번째 그룹을 사용하고 밑줄을 추가하고 세 번째 그룹을 사용하고 두 번째 그룹을 사용하고 다른 밑줄을 추가한 다음 네 번째 그룹을 사용하려고 합니다. 결과 문자열은 아래와 같을 것입니다.
L_ro_em i_sp_um d_lo_or s_ti_ a_em_t c_no_sectetuer f_ue_giat f_ma_es m_la_esuada p_er_tium e_eg_stas.
${name}
사용하여 대체를 위해 명명된 그룹을 사용할 수도 있습니다.
정규식을 가지고 놀려면 정규식 작동 방식에 대한 많은 세부 정보를 제공하는 http://regex101.com/ 을 추천합니다. 또한 선택할 수 있는 몇 가지 정규식 엔진을 제공합니다.
Ricardo Nolde
캡처링 그룹을 사용하여 표현식을 구성하고 구문 분석할 수 있습니다. 캡처하지 않는 그룹에는 첫 번째 이점이 있지만 두 번째에 대한 오버헤드는 없습니다. 예를 들어 캡처하지 않는 그룹은 선택 사항이라고 말할 수 있습니다.
숫자 텍스트를 일치시키고 싶지만 일부 숫자는 1st, 2nd, 3rd, 4th,...로 쓰여질 수 있다고 가정해 봅시다. .
([0-9]+)(?:st|nd|rd|th)?
1, 2, 3... 형식 또는 1st, 2nd, 3rd... 형식의 숫자와 일치하지만 숫자 부분만 캡처합니다.
Bill the Lizard
?:
표현식을 그룹화하고 싶지만 문자열의 일치/캡처 부분으로 저장하고 싶지 않을 때 사용합니다.
예를 들어 IP 주소와 일치하는 항목이 있습니다.
/(?:\d{1,3}\.){3}\d{1,3}/
처음 3개의 옥텟을 저장하는 데는 신경 쓰지 않지만 (?:...)
그룹화를 사용하면 일치 항목을 캡처하고 저장하는 오버헤드를 발생시키지 않고 정규식을 줄일 수 있습니다.
RC.
이는 그룹을 캡처하지 않게 합니다. 즉, 해당 그룹과 일치하는 하위 문자열이 캡처 목록에 포함되지 않습니다. 차이점을 설명하기 위한 루비의 예:
"abc".match(/(.)(.)./).captures #=> ["a","b"] "abc".match(/(?:.)(.)./).captures #=> ["b"]
sepp2k
역사적 동기:
non-capturing 그룹의 존재는 괄호를 사용하여 설명할 수 있습니다.
표현 고려 (a|b)c
와 a|bc
이상의 인해 연결의 우선 순위를 |
, 이 표현식은 두 개의 다른 언어(각각 {ac, bc}
및 {a, bc}
)를 나타냅니다.
그러나 괄호는 일치 그룹으로도 사용됩니다(다른 답변에서 설명한 대로...).
괄호를 사용하지만 하위 표현식을 캡처하지 않으려는 경우 NON-CAPTURING GROUPS를 사용합니다. 예에서 (?:a|b)c
user2369060
예를 들어 이것을 시도해 보겠습니다.
정규식 코드: (?:animal)(?:=)(\w+)(,)\1\2
검색 문자열:
1행 - animal=cat,dog,cat,tiger,dog
2행 - animal=cat,cat,dog,dog,tiger
3행 - animal=dog,dog,cat,cat,tiger
(?:animal)
--> 캡처되지 않은 그룹 1
(?:=)
--> 캡처되지 않은 그룹 2
(\w+)
--> 캡처된 그룹 1
(,)
--> 캡처된 그룹 2
\1
--> 캡처된 그룹 1의 결과 즉, 라인 1은 고양이, 라인 2는 고양이, 라인 3은 개입니다.
\2
--> 캡처된 그룹 2의 결과, 즉 쉼표(,)
따라서 이 코드에서 \1
및 \2
를 제공하여 나중에 코드에서 각각 캡처된 그룹 1 및 2의 결과를 호출하거나 반복합니다.
코드 순서에 따라 (?:animal)
은 그룹 1이어야 하고 (?:=)
는 그룹 2여야 하며 계속됩니다.
?:
를 제공하여 일치 그룹을 캡처하지 않도록 합니다(일치하는 그룹에서 계산되지 않으므로 그룹화 번호는 캡처되지 않은 그룹이 아닌 첫 번째 캡처된 그룹에서 시작함). 따라서 일치 결과의 반복 -group (?:animal)
은 나중에 코드에서 호출할 수 없습니다.
이것이 비 캡처링 그룹의 사용을 설명하기를 바랍니다.
shekhar gehlot
당신이 정규식에서 나중에 사용할 수있는 캡처 그룹에 맞게 또는 당신은 정규식의 교체 부품에 사용할 수 있습니다. 캡처하지 않는 그룹을 만들면 이러한 이유 중 하나로 인해 해당 그룹이 사용되지 않습니다.
캡처하지 않는 그룹은 다양한 항목을 캡처하려고 하고 캡처하고 싶지 않은 그룹이 있는 경우 유용합니다.
그것이 그들이 존재하는 이유입니다. 그룹에 대해 배우는 동안 Atomic Groups에 대해 배우십시오. 그룹은 많은 일을 합니다! 둘러보기 그룹도 있지만 조금 더 복잡하고 많이 사용되지 않습니다.
나중에 정규식(역참조)에서 사용하는 예:
<([AZ][A-Z0-9]*)\b[^>]*>.*?</\1>
[ xml 태그를 찾습니다(ns 지원 없음) ]
([AZ][A-Z0-9]*)
는 캡처 그룹입니다(이 경우 태그 이름).
나중에 정규식에서 \1
([AZ][A-Z0-9]*)
그룹)에 있는 것과 동일한 텍스트만 일치함을 의미합니다(이 경우 종료 태그와 일치함). ).
Bob Fincheimer
tl;dr non-capturing 그룹은 이름에서 알 수 있듯이 일치에 포함되고 싶지 않은 정규식의 일부이며 ?:
는 그룹을 캡처하지 않는 것으로 정의하는 방법입니다.
example@example.com
이라고 가정해 보겠습니다. 다음 정규식은 id 부분과 @example.com 부분의 두 그룹을 만듭니다. (\p{Alpha}*[az])(@example.com)
. @
문자를 포함한 전체 도메인 이름을 추출합니다.
이제 주소의 id 부분만 필요하다고 가정해 보겠습니다. ()
로 둘러싸인 일치 결과의 첫 번째 그룹을 잡는 것이고 이것을 수행하는 방법은 캡처하지 않는 그룹 구문, 즉 ?:
입니다. 따라서 정규식 (\p{Alpha}*[az])(?:@example.com)
은 이메일의 id 부분만 반환합니다.
Aaron S
나는 이것을 말하기 위해 상위 답변에 대해 언급할 수 없습니다. 상위 답변에만 암시된 명시적인 요점을 추가하고 싶습니다.
비 캡처 그룹 (?...)
은 원래 전체 일치에서 문자를 제거 하지 않고 프로그래머에게 시각적으로 정규식을 재구성 할 뿐입니다.
정의된 관련 없는 문자 없이 정규식의 특정 부분에 액세스하려면 항상 .group(<index>)
Scott Anderson
글쎄, 나는 JavaScript 개발자이고 JavaScript와 관련된 그것의 중요성을 설명하려고 노력할 것입니다.
당신이 일치하려는 시나리오를 고려 cat is animal
이 일치 고양이과 동물을 좋아하는 것 모두가이해야 할 때 is
그들 사이에.
// this will ignore "is" as that's is what we want "cat is animal".match(/(cat)(?: is )(animal)/) ; result ["cat is animal", "cat", "animal"] // using lookahead pattern it will match only "cat" we can // use lookahead but the problem is we can not give anything // at the back of lookahead pattern "cat is animal".match(/cat(?= is animal)/) ; result ["cat"] //so I gave another grouping parenthesis for animal // in lookahead pattern to match animal as well "cat is animal".match(/(cat)(?= is (animal))/) ; result ["cat", "cat", "animal"] // we got extra cat in above example so removing another grouping "cat is animal".match(/cat(?= is (animal))/) ; result ["cat", "animal"]
Gaurav
복잡한 정규식에서 많은 수의 그룹을 사용하려는 상황이 발생할 수 있습니다. 그 중 일부는 반복 일치를 위해 있고 일부는 역참조를 제공하기 위해 있습니다. 기본적으로 각 그룹과 일치하는 텍스트는 역참조 배열에 로드됩니다. 많은 그룹이 있고 역참조 배열에서 그 중 일부만 참조할 수 있어야 하는 경우 이 기본 동작을 재정의하여 정규식에 특정 그룹이 반복 처리를 위해서만 존재하며 캡처 및 저장할 필요가 없음을 알릴 수 있습니다. 역참조 배열에서
Jack Peng
내가 발견한 한 가지 흥미로운 점은 캡처하지 않는 그룹 내부에 캡처 그룹을 가질 수 있다는 사실입니다. 일치하는 웹 URL에 대한 아래 정규식을 살펴보십시오.
var parse_url_regex = /^(?:([A-Za-z]+):)(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;
입력 URL 문자열:
var url = "http://www.ora.com:80/goodparts?q#fragment";
내 정규 표현식의 첫 번째 그룹은 (?:([A-Za-z]+):)
프로토콜 방식과 대장과 일치하는 비 캡처 그룹 :
문자를 즉 http:
내가 코드를 아래에 실행되었을 때, 나는보고 있었다 반환되는 배열의 첫번째 인덱스는 문자열이 포함 된 http
내가 생각했을 때 http
대장 :
그들은 비 캡처 그룹 내에있는대로 모두가보고되지 않습니다.
console.debug(parse_url_regex.exec(url));
첫 번째 그룹 (?:([A-Za-z]+):)
이 캡처하지 않는 그룹이면 출력 배열에서 http
문자열을 반환하는 이유가 무엇인지 생각했습니다.
따라서 non-capturing 그룹 내부에 중첩 그룹 ([A-Za-z]+)
중첩 된 그룹 ([A-Za-z]+)
포획 기 (갖는 아니다 ?:
비 - 포착 기 내부 자체 시작시) (?:([A-Za-z]+):)
. 그렇기 때문에 텍스트 http
여전히 캡처되지만 비 캡처 그룹 내부에 있지만 캡처 그룹 외부에 있는 :
RBT
매우 간단합니다. 간단한 날짜 예제로 이해할 수 있습니다. 날짜가 2019년 1월 1일 또는 2019년 5월 2일 또는 다른 날짜로 언급되고 단순히 dd/mm/yyyy 형식으로 변환하려는 경우 해당 월의 이름은 해당 문제에 대해 1월 또는 2월이므로 (선택 사항) 접미사가 아닌 숫자 부분을 캡처하려면 비 캡처 그룹을 사용할 수 있습니다.
정규 표현식은
([0-9]+)(?:January|February)?
그것만큼 간단합니다.
Naved Ahmad
나는 당신에게 대답을 줄 것이라고 생각합니다. 일치가 성공했는지 확인하지 않고 캡처 변수를 사용하지 마십시오.
캡처 변수 $1
등은 일치가 성공하지 않고 지워지지 않는 한 유효하지 않습니다.
#!/usr/bin/perl use warnings; use strict; $_ = "bronto saurus burger"; if (/(?:bronto)? saurus (steak|burger)/) { print "Fred wants a $1"; } else { print "Fred dont wants a $1 $2"; }
$1
bronto를 캡처하는 것을 피하기 위해 (?:)
가 사용됩니다.
패턴이 일치하면 $1
이 다음 그룹화된 패턴으로 캡처됩니다.
따라서 출력은 아래와 같을 것입니다.
Fred wants a burger
일치 항목을 저장하지 않으려는 경우에 유용합니다.
Harini
Google Chrome devTools를 열고 콘솔 탭을 열고 다음을 입력합니다.
"Peace".match(/(\w)(\w)(\w)/)
실행하면 다음이 표시됩니다.
["Pea", "P", "e", "a", index: 0, input: "Peace", groups: undefined]
JavaScript
RegExp 엔진은 인덱스가 1,2,3인 항목의 세 그룹을 캡처합니다. 이제 non-capturing 표시를 사용하여 결과를 확인하십시오.
"Peace".match(/(?:\w)(\w)(\w)/)
결과는 다음과 같습니다.
["Pea", "e", "a", index: 0, input: "Peace", groups: undefined]
이것은 비 캡처 그룹이 무엇인지 분명합니다.
AmerllicA
간단한 답변
여러 가능성 중 하나가 여기 (?:one|two)
또는 선택적 구 camp(?:site)?
또는 일반적으로 구체적으로 참조할 필요 없이 그룹/구/섹션을 참조하려는 모든 곳.
캡처된 그룹 수를 최소로 유지합니다.
Cyberwip
(?: ... ) 그룹( ... ) 역할을 하지만 일치하는 데이터를 캡처하지 않습니다. 표준 캡처 그룹보다 훨씬 더 효율적입니다. 무언가를 그룹화하고 싶지만 나중에 재사용할 필요가 없을 때 사용합니다. @토토
user8998146
출처 : http:www.stackoverflow.com/questions/3512471/what-is-a-non-capturing-group-in-regular-expressions
'etc. > StackOverFlow' 카테고리의 다른 글
Git에서 삭제된 숨김을 복구하는 방법은 무엇입니까? (0) | 2021.12.08 |
---|---|
Linux에서 파일을 어떻게 심볼릭 링크할 수 있습니까? [닫은] (0) | 2021.12.07 |
Microsoft JSON 날짜 형식은 어떻게 지정합니까? (0) | 2021.12.07 |
파이썬에서 객체에 속성이 있는지 확인하는 방법 (0) | 2021.12.07 |
Node.js에서 종료하는 방법 (0) | 2021.12.07 |