[regex] 여러 반복 그룹을 캡처하는 방법은 무엇입니까?

동일한 패턴의 여러 그룹을 캡처해야합니다. 다음 문자열이 있다고 가정합니다.

HELLO,THERE,WORLD

그리고 다음 패턴을 작성했습니다.

^(?:([A-Z]+),?)+$

내가 원하는 것은 그룹 1이 “HELLO”, 그룹 2는 “THERE”, 그룹 3은 “WORLD”가되도록 모든 단어를 캡처하는 것입니다. 내 정규식이 실제로 마지막 하나만 캡처하는 ” 세계”.

여기에서 정규 표현식을 테스트 하고 있으며 Swift와 함께 사용하고 싶습니다 (스위프트에 어떻게 든 중간 결과를 얻을 수있는 방법이있을 수 있으므로 사용할 수 있습니까?)

업데이트 : 사용하고 싶지 않습니다 split. 이제 마지막 그룹뿐만 아니라 패턴과 일치하는 모든 그룹을 캡처하는 방법 만 있으면됩니다.



답변

패턴에 하나의 그룹이 있으면 해당 그룹에서 정확한 결과를 하나만 얻을 수 있습니다. 캡처 그룹이 패턴에 의해 반복되는 경우 ( +주변 비 캡처 그룹 에서 수량자를 사용함 ) 일치하는 마지막 값만 저장됩니다.

패턴의 모든 일치 항목찾기 위해 언어의 정규식 구현 함수를 사용해야합니다 . 그런 다음 비 캡처 그룹의 앵커와 수량자를 제거해야합니다 (비 캡처 그룹 자체도 생략 할 수 있음).

또는 정규식을 확장하고 결과에서 얻고 자하는 그룹당 하나의 캡처 그룹을 패턴에 포함 시키십시오.

^([A-Z]+),([A-Z]+),([A-Z]+)$


답변

이런 게 필요한 것 같아요 ….

b="HELLO,THERE,WORLD"
re.findall('[\w]+',b)

Python3에서 반환되는

['HELLO', 'THERE', 'WORLD']


답변

답변에 단락 2의 추가 예를 제공하기 위해. 한 그룹을 사용하여 세 경기를하는 것보다 한 경기에서 세 그룹을 얻는 것이 얼마나 중요한지 잘 모르겠습니다. 예 : 그루비에서 :

def subject = "HELLO,THERE,WORLD"
def pat = "([A-Z]+)"
def m = (subject =~ pat)
m.eachWithIndex{ g,i ->
  println "Match #$i: ${g[1]}"
}

Match #0: HELLO
Match #1: THERE
Match #2: WORLD


답변

Byte Commander의 답변을 읽은 후 가능한 약간의 개선 사항을 소개하고 싶습니다.

미리 결정된 한 두 n단어 중 하나와 일치하는 정규 표현식을 생성 할 수 있습니다 n. 예를 들어 1 ~ 3 개의 단어를 일치 시키려면 정규 표현식 :

^([A-Z]+)(?:,([A-Z]+))?(?:,([A-Z]+))?$

다음 문장을 1 개, 2 개 또는 3 개의 캡처 그룹과 일치시킵니다.

HELLO,LITTLE,WORLD
HELLO,WORLD
HELLO

Regex101 에서이 정규식에 대한 자세한 설명을 볼 수 있습니다 .

내가 말했듯이 좋아하는 언어를 사용하여 원하는 그룹에 대해이 정규식을 생성하는 것은 매우 쉽습니다. 나는 빠른 사람이 아니기 때문에 다음은 루비 예제입니다.

def make_regexp(group_regexp, count: 3, delimiter: ",")
  regexp_str = "^(#{group_regexp})"
  (count - 1).times.each do
    regexp_str += "(?:#{delimiter}(#{group_regexp}))?"
  end
  regexp_str += "$"
  return regexp_str
end

puts make_regexp("[A-Z]+")

즉,이 경우 정규식을 사용하지 않는 것이 좋습니다 split. 필요에 따라 단순한 토큰 화 패턴에서 일부 토큰 화 패턴 까지 다른 많은 훌륭한 도구 가 있습니다. IMHO, 정규 표현식은 그중 하나가 아닙니다. 예를 들어 루비에서는 str.split(",")또는 같은 것을 사용합니다.str.scan(/[A-Z]+/)


답변

주요 차이점은 반복 된 그룹캡처하는 대신 캡처 된 그룹을 반복하는 것입니다 .

이미 알고 있듯이 캡처 된 그룹을 반복하면 마지막 반복 만 캡처된다는 차이점이 있습니다. 반복 된 그룹을 캡처하면 모든 반복이 캡처됩니다.

PCRE (PHP) :

((?:\w+)+),?
Match 1, Group 1.    0-5      HELLO
Match 2, Group 1.    6-11     THERE
Match 3, Group 1.    12-20    BRUTALLY
Match 4, Group 1.    21-26    CRUEL
Match 5, Group 1.    27-32    WORLD

모든 캡처가 그룹 1에 있으므로 $1교체 만하면됩니다.

이 정규식의 다음과 같은 일반적인 형식을 사용했습니다.

((?:{{RE}})+)

regex101의


답변

실제로 여러 번 일치하는 하나의 캡처 그룹이 있습니다. 여러 캡처 그룹이 아닙니다.

자바 스크립트 (js) 솔루션 :

let string = "HI,THERE,TOM";
let myRegexp = /([A-Z]+),?/g;       //modify as you like
let match = myRegexp.exec(string);  //js function, output described below
while(match!=null){                 //loops through matches
    console.log(match[1]);          //do whatever you want with each match
    match = myRegexp.exec(bob);     //find next match
}

산출:

HI
THERE
TOM

통사론:

// matched text: match[0]
// match start: match.index
// capturing group n: match[n]

보시다시피, 이것은 모든 경기에서 작동합니다.


답변

내 대답이 늦었다는 것을 알고 있지만 오늘 나에게 발생하며 다음 접근 방식으로 해결했습니다.

^(([A-Z]+),)+([A-Z]+)$

따라서 첫 번째 그룹 (([A-Z]+),)+은 마지막 패턴 ([A-Z]+)과 일치하는 마지막 패턴을 제외한 모든 반복 패턴 과 일치합니다. 그리고 이것은 문자열에서 반복되는 그룹의 수에 관계없이 동적입니다.