[regex] 정규식에서 캡처하지 않은 그룹이란 무엇입니까?

캡처하지 않은 그룹, 즉 (?:)정규 표현식에 어떻게 사용되며 어떤 이점이 있습니까?



답변

이것을 예로 들어 설명해 드리겠습니다.

다음 텍스트를 고려하십시오.

http://stackoverflow.com/
/programming/tagged/regex

이제 정규식을 아래에 적용하면 …

(https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?

… 나는 다음과 같은 결과를 얻을 것입니다 :

Match "http://stackoverflow.com/"
     Group 1: "http"
     Group 2: "stackoverflow.com"
     Group 3: "/"

Match "/programming/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 "/programming/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 자 이상의 단어와 일치하며 그룹을 사용하여 처음 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/을 권장합니다. http://regex101.com/ 은 정규식의 작동 방식에 대한 자세한 내용을 제공합니다. 또한 선택할 수있는 몇 가지 정규식 엔진을 제공합니다.


답변

캡처 그룹을 사용하여 식을 구성하고 구문 분석 할 수 있습니다. 캡처하지 않은 그룹은 첫 번째 이점이 있지만 두 번째 그룹의 오버 헤드는 없습니다. 예를 들어 캡처하지 않은 그룹은 선택 사항이라고 말할 수 있습니다.

숫자 텍스트를 일치 시키려고하지만 일부 숫자는 1, 2, 3, 4로 기록 될 수 있습니다. 숫자 부분을 캡처하려면 (선택적) 접미사는 제외하고 캡처하지 않는 그룹을 사용할 수 있습니다 .

([0-9]+)(?:st|nd|rd|th)?

1, 2, 3 … 또는 1, 2, 3, … 형식의 숫자와 일치하지만 숫자 부분 만 캡처합니다.


답변

?: 식을 그룹화 할 때 사용되지만 문자열의 일치 / 캡처 된 부분으로 저장하지는 않습니다.

예를 들어 IP 주소와 일치하는 것이 있습니다.

/(?:\d{1,3}\.){3}\d{1,3}/

처음 3 옥텟을 저장하는 것에 대해서는 신경 쓰지 않지만 (?:...)그룹화를 사용하면 일치하는 캡처 및 저장 오버 헤드가 발생하지 않고 정규 표현식을 단축 할 수 있습니다.


답변

그룹을 캡처하지 못하게하므로 해당 그룹과 일치하는 하위 문자열이 캡처 목록에 포함되지 않습니다. 차이점을 설명하기위한 루비의 예 :

"abc".match(/(.)(.)./).captures #=> ["a","b"]
"abc".match(/(?:.)(.)./).captures #=> ["b"]


답변

역사적 동기 :

비 캡처 그룹의 존재는 괄호를 사용하여 설명 할 수 있습니다.

식을 고려 (a|b)c하고 a|bc인해 연결을 통해 우선 순위로, |이 표현은 두 개의 서로 다른 언어 (대표 {ac, bc}하고 {a, bc}각각을).

그러나 괄호는 일치하는 그룹으로도 사용됩니다 (다른 답변에서 설명한 것처럼 …).

괄호를 갖고 싶지만 하위 표현식을 캡처하지 않으려면 비 캡처 그룹을 사용하십시오. 이 예에서는(?:a|b)c


답변

예를 들어 이것을 시도해 보겠습니다.

정규식 코드 : (?: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 여야하며 계속되어야합니다.

그러나 ?:일치 그룹을 캡처하지 않으면 (일치 그룹에서 계산되지 않으므로 그룹 번호는 첫 번째 캡처 그룹에서 시작하고 캡처되지 않은 그룹에서 시작) 일치 그룹 결과의 반복 (?:animal)나중에 코드에서 호출 할 수 없습니다.

이것이 비 캡처 그룹의 사용을 설명하기를 바랍니다.

여기에 이미지 설명을 입력하십시오


답변

캡처 한 그룹은 나중에 정규식에서 사용하여 일치 시키 거나 정규식 의 대체 부분에서 사용할 수 있습니다. 캡처하지 않는 그룹을 만들면 해당 그룹이 이러한 이유로 사용되지 않습니다.

캡처하지 않는 그룹은 여러 가지 다른 것을 캡처하려고하고 캡처하지 않으려는 그룹이있는 경우 유용합니다.

그것이 그들이 존재하는 이유와 거의 같습니다. 그룹에 대해 배우고 원자 그룹에 대해 배우 면 많은 일을합니다! 둘러보기 그룹도 있지만 조금 더 복잡하고 많이 사용되지는 않습니다.

정규식에서 나중에 사용하는 예 (역 참조) :

<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1> [ss 지원없이 xml 태그를 찾습니다]]

([A-Z][A-Z0-9]*) 캡처 그룹 (이 경우 태그 이름)

나중에 정규 표현식 \1에서 첫 번째 그룹 ( ([A-Z][A-Z0-9]*)그룹) 과 동일한 텍스트 만 일치합니다 (이 경우 종료 태그와 일치 함).