2010-05-12 16 views
77

Jestem początkującym wyrażenie regularne, a ja nie dość dowiedzieć się jak napisać wyrażenie regularne, że „mecz” zduplikowane kolejne słowa takie jak:wyrażenie regularne dla kolejnych powtarzających się słów

Paryż w ze sprężyną.

Nie , że ten jest powiązany.

Dlaczego się śmiejesz? Czy moje moje wyrażeń regularnych, że zły?

Czy istnieje jedno wyrażenie regularne pasujące do WSZYSTKICH pogrubionych ciągów powyżej?

+3

Nie, to nie jest praca domowa. Wstydzę się ludzkości z tego powodu, że niektórzy używają StackOverflow do wykonania swojej pracy domowej. – Joshua

+4

@poly: To nie było "oskarżenie", ale spokojne, normalne pytanie, które idealnie może przyjąć "nie" jako odpowiedź. @Joshua: Tak, niektórzy ludzie (nie za mało) niech ta strona zrobi dla nich pracę domową. Ale zadawanie pytań o zadania domowe nie jest złym zadaniem w SO, gdy są one oznaczone jako takie. Zwykle styl odpowiedzi zmienia się z "tutaj jest rozwiązanie" na "tutaj są pewne rzeczy, o których nie myślałeś", i to jest dobre. Ktoś musi starać się utrzymać rozróżnienie, w jego przypadku to ja, a gdzie indziej "inni ludzie" robią to samo. To wszystko. – Tomalak

+7

Mam nadzieję, że nigdy nie zobaczę pytania typu "To brzmi trochę jak pytanie o miejsce pracy." a następnie ludzie będą argumentować, czy przepełnienie stosu wykonuje czyjąś pracę. – marcio

Odpowiedz

87

Spróbuj tego wyrażenia regularnego:

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

Tutaj \b jest granica słowo i \1 referencje zrobionego mecz z pierwszej grupy.

+1

Sprawia, że ​​zastanawiam się; czy można też wykonać '\ 0'? (Gdzie '\ 0' jest całością wyrażenia regularnego, aż do bieżącego punktu LUB gdzie" \ 0 "odnosi się do całego wyrażenia) – Pindatjuh

+0

@Pindatjuh: Nie, nie sądzę, ponieważ ten podrzędny element byłby również częścią cały mecz. – Gumbo

+0

Przynajmniej działa na silniku regex używanym w oknie wyszukiwania/zamiany Eclipse. –

3

Nie. To jest nieregularna gramatyka. Mogą występować wyrażenia regularne specyficzne dla silnika/języka, z których można korzystać, ale nie ma uniwersalnego wyrażenia regularnego, które mogłoby to zrobić.

+12

Chociaż mam rację w ścisłym sensie, uważam, że nie ma już silnego silnika regex, który nie obsługuje grupowania i odsyłaczy wstecz. – Tomalak

4

Szeroko stosowany PCRE biblioteka może obsługiwać takie sytuacje (nie będzie osiągnąć The samo z silnikami zgodnymi z POSIX regex, choć):

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

Potrzebujesz czegoś, aby dopasować znaki * pomiędzy * dwoma słowami, jak' \ W + '. '\ b' nie zrobi tego, ponieważ nie zużywa żadnych znaków. –

+0

Wielkie dzięki, naprawione. – soulmerge

+0

To potencjalnie spowoduje fałszywe-pozytywne dopasowanie w przypadkach takich jak "... te problemy ...". To rozwiązanie nie jest tak niezawodne, jak ogólna struktura Gumbo, która wystarczająco implementuje granice słów. – mickmackusa

15

Uważam ten regex obsługuje kolejne sytuacje:

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

dobry wybór strun testów można znaleźć tutaj: http://callumacrae.github.com/regex-tuesday/challenge1.html

+0

Świetne, działa z apostrofami/łącznikami/itd. też - dzięki! – JoeRocc

+0

dla linku challenge1, co umieścisz w obszarze wymiany, aby użyć zgrupowanego słowa? Wypróbowałem '\ 0' ale nie działa. – uptownhr

+1

Nie zostanie przechwycony w trzech powtórzeniach (lub więcej), a nie gdy jedno z dup/trzech kopii znajduje się na końcu ciągu znaków – Nico

2

przykładzie w JavaScript: The Good Parts można dostosować, aby to zrobić:

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

\ b \ W wykorzystuje do granic tekstu, gdzie \ W jest odpowiednikiem [0-9a-Z_a-Z]. Jeśli nie masz nic przeciwko temu ograniczeniu, zaakceptowana odpowiedź jest w porządku.

2

To regex używam do usuwania zduplikowanych frazy w moim skurczowej bot:

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

(\S+\s*) wygląda na dowolny ciąg znaków, który nie jest białe znaki, a następnie spacje.

\1{2,} następnie szuka więcej niż 2 wystąpienia tego wyrażenia w ciągu znaków, aby dopasować. Jeśli są 3 frazy, które są identyczne, to pasuje.

+0

Ta odpowiedź jest myląca. Nie wyszukuje duplikatów, poluje na podłańcuchy z 3 lub więcej wystąpieniami. Nie jest również bardzo wytrzymały ze względu na '\ s *' w grupie przechwytującej. Zobacz tę demonstrację: https://regex101.com/r/JtCdd6/1 – mickmackusa

+0

Ponadto ekstremalne przypadki (tekst o niskiej częstotliwości) będą powodować fałszywie dodatnie mecze. Na przykład. "Powiedziałem" oioioi ", to jakiś niegodziwy błąd!' Na 'oioioi' i' sss' – mickmackusa

1

To wyrażenie (inspirowany z Mike, powyżej) wydaje się złapać wszystkie duplikaty trzech kopii, itp, w tym te, które na końcu łańcucha, który większość innych nie:

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

I znać pytanie zadane dopasować powiela tylko, ale trzykrotnego znajduje się zaledwie 2 duplikaty obok siebie :)

Najpierw kładę (^|\s+) aby upewnić się, że zaczyna się od pełnego wyrazu, inaczej „stek dziecka” pójdzie do "child'steak" (pasują do "s"). Następnie dopasowuje wszystkie pełne słowa ((\b\S+\b)), a następnie koniec ciągu znaków ($) lub liczbę spacji (\s+), całość powtórzona więcej niż raz.

Próbowałem to tak i to działa dobrze:

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 
+0

Mam problem z przepisaniem tego na PHP, ważne jest, aby uzyskać pojedynczą kopię dopasowanego duplikatu zastępując każde wystąpienie duplikatów/potrójnych itp. .Do tej pory mam: preg_replace ('/ (^ | \ s +) (\ S +) (($ | \ s +) \ 2) +/im', '$ 0', $ string); – AdamJones

0

użyć w przypadku, gdy chcesz bez uwzględniania wielkości liter sprawdzanie dla zduplikowanych słów.

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

Używanie modyfikatora wzorca niewrażliwego na wielkość liter nie ma zastosowania do wzorca. Nie ma zakresów liter, które mogłyby wpłynąć na flagę. – mickmackusa

+0

To jest faktycznie duplikat zaakceptowanej odpowiedzi i nie dodaje żadnej wartości do strony. Rozważ usunięcie tej odpowiedzi, aby zmniejszyć nadmiar strony. – mickmackusa

3

Spróbuj tego z poniżej RE

  • \ b początku słowo słowo granicy
  • \ w + dowolne słowo charakteru
  • \ 1 samo słowo pasuje już
  • \ b końcu wyrazu
  • () * Powtarzanie ponownie

    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(); 
    } 
    
0

Ponieważ niektórzy deweloperzy idą do tej strony w poszukiwaniu rozwiązania, które nie tylko eliminuje duplikaty kolejne podciągi non-spacją, ale trzy powtórzenia i poza nią, pokażę dostosowanej wzór.

Wzór: /(\b\S+)(?:\s+\1\b)+/ (Pattern Demo)
Wymienić: $1 (zamiennik meczu fullstring z grupy capture # 1)

Ten wzór łapczywie odpowiada "całość" non-białymi podciąg, następnie wymaga jednego lub więcej kopii dopasowany podciąg, który może być ograniczony przez jeden lub więcej znaków białych znaków (spacja, tabulacja, znak nowej linii itp.).

Konkretnie:

  • \b (granica słowo) znaki są niezbędne, aby zapewnić częściowe słowa nie pasują do siebie.
  • Drugi nawias jest grupą niezapisującą, ponieważ ten podciąg o zmiennej szerokości nie musi być przechwytywany - tylko dopasowany/zaabsorbowany.
  • + (jeden lub więcej kwantyfikator) w grupie bez przechwytywania jest bardziej odpowiednia niż * ponieważ * będzie „przeszkadza” silnik regex uchwycić i zastąpienie pojedynczych, wystąpienia - jest marnotrawstwem wzornictwo.

* uwaga: jeśli masz do czynienia ze zdaniami lub ciągami wejściowymi z interpunkcją, to wzór będzie musiał zostać dopracowany.

+0

@AdamJones używaj tego wzorca w swoim projekcie php. Odpowiedź Nico ma niepotrzebną składnię. – mickmackusa

Powiązane problemy