중복 단어에 대한 정규식


114

저는 정규식 초보자이고 다음과 같은 중복 된 연속 단어를 "일치"하는 단일 정규식을 작성하는 방법을 알 수 없습니다.

파리 하여 봄.

아니 그 그 관계가있다.

왜 웃어요? 인가 내 내 정규 표현식은 나쁜?

위의 모든 굵은 문자열과 일치하는 단일 정규식이 있습니까?


4
@poly : 그것은 "고발"이 아니라 대답으로 완벽하게 "아니오"를 취할 수있는 차분하고 평범한 질문이었습니다. @Joshua : 예, 어떤 사람들은 (너무 적지 않은)이 사이트에서 숙제를하도록합니다. 그러나 숙제 질문을하는 것은 그렇게 태그가 붙을 때 그렇게하기에 나쁜 일이 아닙니다. 일반적으로 답변의 스타일은 "여기에 해결책이 있습니다"에서 "생각하지 않은 몇 가지 사항이 있습니다"로 변경되며 이는 좋은 것입니다. 누군가는 구별을 유지하려고 노력해야합니다. 그의 경우는 저 였고 다른 곳에서는 "다른 사람들"도 같은 일을합니다. 그게 다야.
Tomalak

13
"이건 직장 질문처럼 들리는군요. 그렇죠?"와 같은 질문을 보지 않기를 바랍니다. 사람들은 스택 오버플로가 누군가의 일을하고 있는지 논쟁 할 것입니다.
marcio

수락 한 정규식 솔루션과 관련하여 @Joshua +1, 일치 항목 (중복 항목)을 쌍의 한 요소 (예 : not that that is related-> not that is related)로 대체 할 수있는 방법을 알려주세요 . 미리 감사드립니다
Antoine

@Joshua 나는 해결책을 찾았다 고 생각합니다 : 나는 대체해야합니다 \1!
Antoine

2
@DavidLeal 어때요 \b(\w+)\s+(\1\s*)+\b?
ytu

답변:


141

다음 정규식을 시도하십시오.

\b(\w+)\s+\1\b

다음 \b은 단어 경계이며 \1첫 번째 그룹의 캡처 된 일치를 참조합니다.


1
내가 궁금합니다; \0너무 할 수 있습니까? ( \0현재 지점까지 전체 정규식이 어디에 \0
있거나

@Pindatjuh : 아니요, 하위 경기가 전체 경기의 일부가 될 것이기 때문에 그렇게 생각하지 않습니다.
Gumbo

적어도 Eclipse 검색 / 바꾸기 대화 상자에서 사용되는 정규식 엔진에서 작동합니다.
Chaos_99 2013 년

3
경고 일뿐입니다. 이것은 아포스트로피 나 (노엘이 언급했듯이) 하이펜이있는 단어를 처리하지 않습니다. Mike의 솔루션은 이러한 경우에 더 잘 작동합니다

3
또한, 복제 / 삼중 중 하나가 문자열의 끝에있을 때가 아니라 삼중 (또는 그 이상)을 포착하지 않습니다
Nico

20

이 정규식이 더 많은 상황을 처리한다고 생각합니다.

/(\b\S+\b)\s+\b\1\b/

좋은 테스트 문자열은 여기에서 찾을 수 있습니다 : http://callumacrae.github.com/regex-tuesday/challenge1.html


좋습니다. 아포스트로피 / 하이픈 / 등과 함께 작동합니다. 너무-감사합니다!

challenge1 링크의 경우 그룹화 된 단어를 사용하기 위해 대체 영역에 무엇을 배치합니까? 시도 <strong>\0</strong>했지만 작동하지 않습니다.
uptownhr

2
복제 / 삼중 중 하나가 문자열의 끝에있을 때가 아니라 삼중 (또는 그 이상)을 포착하지 않습니다
Nico

@uptownhr 사용하려는 $1 <strong>$2</strong>. 그러나 다른 정규식도 사용하십시오 /\b(\S+) (\1)\b/gi. 여기 링크가 있습니다 : callumacrae.github.io/regex-tuesday/…
dsalaj

<p class="bebe">bla bla</p>이 정규식 수식을 통합하는 방법 과 같이 특정 태그에서 모든 연속 단어를 찾으려면 어떻게해야합니까?
Just Me

7

아래 RE로 시도하십시오.

  • \ b 단어 단어 경계의 시작
  • \ W + 모든 단어 문자
  • \ 1 이미 일치하는 같은 단어
  • \ b 단어 끝
  • () * 다시 반복

    public static void main(String[] args) {
    
        String regex = "\\b(\\w+)(\\b\\W+\\b\\1\\b)*";//  "/* Write a RegEx matching repeated words here. */";
        Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE/* Insert the correct Pattern flag here.*/);
    
        Scanner in = new Scanner(System.in);
    
        int numSentences = Integer.parseInt(in.nextLine());
    
        while (numSentences-- > 0) {
            String input = in.nextLine();
    
            Matcher m = p.matcher(input);
    
            // Check for subsequences of input that match the compiled pattern
            while (m.find()) {
                input = input.replaceAll(m.group(0),m.group(1));
            }
    
            // Prints the modified sentence.
            System.out.println(input);
        }
    
        in.close();
    }

5

널리 사용되는 PCRE 라이브러리는 이러한 상황을 처리 할 수 ​​있습니다 ( 하지만 POSIX 호환 정규식 엔진으로 동일하게 달성 할 수 없습니다 ).

(\b\w+\b)\W+\1

두 단어 사이 의 문자를 일치시킬 무언가가 필요합니다 \W+. \b문자를 소비하지 않기 때문에하지 않습니다.
Alan Moore

이것은 잠재적으로 ... the these problems.... 이 솔루션은 단어 경계를 충분히 구현하는 Gumbo 패턴의 일반적인 구조만큼 신뢰할 수 없습니다.
mickmackusa

<p class="bebe">bla bla</p>이 정규식 수식을 통합하는 방법 과 같이 특정 태그에서 모든 연속 단어를 찾으려면 어떻게해야합니까?
Just Me

4

이것은 내 트 위치 봇에서 중복 문구를 제거하는 데 사용하는 정규식입니다.

(\S+\s*)\1{2,}

(\S+\s*) 공백이 아닌 문자열을 찾은 다음 공백을 찾습니다.

\1{2,}그런 다음 일치시킬 문자열에서 해당 구문의 2 개 이상의 인스턴스를 찾습니다. 동일한 문구가 3 개 있으면 일치합니다.


이 대답은 잘못된 것입니다. 중복을 사냥하지 않고 3 개 이상 발생하는 부분 문자열을 사냥합니다. 또한 \s*포획 그룹에 있기 때문에 매우 견고하지 않습니다 . 이 데모보기 : regex101.com/r/JtCdd6/1
mickmackusa

또한 극단적 인 경우 (빈도가 낮은 텍스트)는 잘못된 긍정 일치를 생성합니다. 예 I said "oioioi" that's some wicked mistressship!에서 oioioisss
mickmackusa

4

연속 된 단어 수를 찾으려면 아래 표현식이 올바르게 작동해야합니다. 일치는 대소 문자를 구분하지 않을 수 있습니다.

String regex = "\\b(\\w+)(\\s+\\1\\b)*";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);

Matcher m = p.matcher(input);

// Check for subsequences of input that match the compiled pattern
while (m.find()) {
     input = input.replaceAll(m.group(0), m.group(1));
}

샘플 입력 : Goodbye goodbye GooDbYe

샘플 출력 : Goodbye

설명:

정규식 :

\ b : 단어 경계의 시작

\ w + : 모든 단어 문자

(\ s + \ 1 \ b) * : 이전 단어와 일치하고 단어 경계로 끝나는 단어가 뒤에 오는 임의의 수의 공백. *로 묶인 모든 것은 하나 이상의 반복을 찾는 데 도움이됩니다.

그룹화 :

m.group (0) : 위의 경우 일치하는 그룹을 포함합니다 Goodbye goodbye GooDbYe

m.group (1) : 위의 경우 일치하는 패턴의 첫 단어를 포함합니다 Goodbye

Replace 메서드는 연속적으로 일치하는 모든 단어를 단어의 첫 번째 인스턴스로 대체합니다.


3

아니요. 그것은 불규칙한 문법입니다. 사용할 수있는 엔진 / 언어 별 정규식이있을 수 있지만이를 수행 할 수있는 범용 정규식은 없습니다.


12
엄격한 의미에서 정확하지만 그룹화 및 역 참조를 지원하지 않는 정규식 엔진이 더 이상 심각하게 사용되지 않는다고 생각합니다.
Tomalak

3

다음은 여러 단어를 여러 번 포착하는 것입니다.

(\b\w+\b)(\s+\1)+

<p class="bebe">bla bla</p>이 정규식 수식을 통합하는 방법 과 같이 특정 태그에서 모든 연속 단어를 찾으려면 어떻게해야합니까?
Just Me

HTML 파싱이 필요하다고 생각합니다. 검색하려는 특정 태그에 대해 HTML 내에서 모든 태그 발생을 찾고이 정규식을 하나씩 실행하십시오. 또는 HTML에서 반복이 발생하는 위치에 신경 쓰지 않는다면 모든 태그 텍스트 속성을 연결하고 연결된 문자열에서 정규식을 실행하십시오
synaptikon

나는 답을 찾았다 <p class="bebe">.*?\b\s+(\w+)\b\K\s+\1\s+\b(?=.*?<\/p>)
그냥 나

3

2 개 이상의 중복 단어 (연속 / 비 연속 단어)를 제거하는 정규식

2 개 이상의 중복 단어를 포착하고 하나의 단어 만 남길 수있는이 정규식을 사용해보세요. 그리고 중복 단어 는 연속적 일 필요도 없습니다 .

/\b(\w+)\b(?=.*?\b\1\b)/ig

여기서는 \bWord Boundary에 ?=사용되며 긍정적 인 예측에 \1사용되며 역 참조에 사용됩니다.

소스


1
연속적이지 않은 것은 나쁜 생각입니다 "the cat sat on the mat".->" cat sat on the mat"
Walf

@Walf True. 그럼에도 불구하고 이것이 의도 된 시나리오가 있습니다. (예 : 데이터 스크랩 중)
Niket Pathak

내가 그것을 고친 후에 왜 정규식을 다시 깨뜨 렸 습니까? 내가 의도를 바꿨다고 생각 했어? 링크 한 예조차도 실수가 없습니다.
Walf

네, 그것은 실수였습니다. 복사가 잘못된 것을 붙여 넣었습니다. 내 예제에서 실제로 복사하려고했습니다. 어쨌든 이제 작동합니다! 너무 좋아! 감사!
Niket Pathak

2

Javascript : The Good Parts의 예를 다음과 같이 조정할 수 있습니다.

var doubled_words = /([A-Za-z\u00C0-\u1FFF\u2800-\uFFFD]+)\s+\1(?:\s|$)/gi;

\ b는 단어 경계에 \ w를 사용합니다. 여기서 \ w는 [0-9A-Z_a-z]와 같습니다. 그 제한이 마음에 들지 않으면 허용되는 대답은 괜찮습니다.


2

일부 개발자는 중복 된 공백이 아닌 하위 문자열을 제거 할뿐만 아니라 3 중 이상을 제거하는 솔루션을 찾기 위해이 페이지를 방문하므로 적응 된 패턴을 보여 드리겠습니다.

패턴 : /(\b\S+)(?:\s+\1\b)+/( 패턴 데모 )
바꾸기 : $1(전체 문자열 일치를 캡처 그룹 # 1로 바꿉니다. )

이 패턴은 "전체"비 공백 하위 문자열과 탐욕스럽게 일치 한 다음 하나 이상의 공백 문자 (공백, 탭, 줄 바꿈 등)로 구분 될 수있는 일치하는 하위 문자열의 하나 이상의 복사본이 필요합니다.

구체적으로 특별히:

  • \b (단어 경계) 문자는 부분 단어가 일치하지 않도록하는 데 중요합니다.
  • 두 번째 괄호는 캡처되지 않는 그룹입니다.이 가변 너비 하위 문자열은 캡처 할 필요가없고 일치 / 흡수 만 가능하기 때문입니다.
  • +비 캡처 그룹 의 (하나 이상의 수량 자) 는 정규식 엔진이 싱글 톤 발생을 캡처하고 대체하기 위해 "귀찮게" *하기 때문에 보다 적절 *합니다. 이것은 낭비적인 패턴 디자인입니다.

* 문장이나 문장 부호가있는 입력 문자열을 다루는 경우 패턴을 더 세분화해야합니다.


@AdamJones는 PHP 프로젝트에서이 패턴을 사용합니다. Nico의 대답에는 불필요한 구문이 있습니다.
mickmackusa

1

이 표현 (위의 Mike에서 영감을 얻음)은 문자열의 끝에있는 것을 포함하여 모든 중복, 삼중 등을 잡는 것처럼 보이지만 대부분은 그렇지 않습니다.

/(^|\s+)(\S+)(($|\s+)\2)+/g, "$1$2")

중복 만 일치하도록 요청한 질문을 알고 있지만 삼중은 서로 옆에 2 개의 중복 만 있습니다. :)

먼저 (^|\s+)전체 단어로 시작하는지 확인합니다. 그렇지 않으면 "child 's steak"가 "child'steak"로 이동합니다 ( "s"가 일치 함). 그런 다음 모든 전체 단어 ( (\b\S+\b))와 문자열의 끝 ( $) 또는 여러 공백 ( \s+)이 뒤 따르고 전체가 두 번 이상 반복됩니다.

나는 이것을 이렇게 시도했고 잘 작동했습니다.

var s = "here here here     here is ahi-ahi ahi-ahi ahi-ahi joe's joe's joe's joe's joe's the result result     result";
print( s.replace( /(\b\S+\b)(($|\s+)\1)+/g, "$1"))         
--> here is ahi-ahi joe's the result

나는 이것을 PHP로 재 작성하는 데 문제가 있습니다. 중복 / 삼중의 각 발생을 대체하는 일치 된 중복의 단일 사본을 얻는 것이 중요합니다. 지금까지 내가 가지고있는 것 : preg_replace ( '/ (^ | \ s +) (\ S +) ( ($ | \ s +) \ 2) + / im ','$ 0 ', $ string);
애덤 존스

이것이 최고의 답변입니다. 다음 \b과 같이 끝에 추가 하여 조정했습니다 . /(^|\s+)(\S+)(($|\s+)\2)+\b/g, "$1$2")그러면 다음과 같은 상황에서 작동합니다 : the the string String string stringing the the along the the stringwill be the string stringing the along the stringNotice string stringing. 귀하의 답변과 일치합니다. 감사합니다.
Ste

-1

중복 단어에 대해 대소 문자를 구분하지 않으려는 경우에 사용하십시오.

(?i)\\b(\\w+)\\s+\\1\\b

대소 문자를 구분하지 않는 패턴 수정자를 사용하는 것은 패턴에 사용되지 않습니다. 플래그가 영향을 미칠 문자 범위가 없습니다.
mickmackusa

이것은 실제로 허용 된 답변의 중복이며 페이지에 값을 추가하지 않습니다. 페이지 팽창을 줄이려면이 답변을 제거하십시오.
mickmackusa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.