2012-06-14 18 views
5

Szukasz perl one-liner co znajdzie wszystkie rozmowę z następnego wzoru:wyszukiwania słowa z powtarzających się znaków

X(not_X_chrs)X(not_X_chrs)X e.g. cyclic 

Dla jednego znaku, nie jest łatwo, na przykład na 'a'

perl -nle 'print if /^a[^a]+a[^a]+a$/' < /usr/share/dict/web2 

ale chcę szukać ANY charakter, więc, patrząc na jedną regex do znalezienia wszystkie takich słów jak:

azalea #repeating a 
baobab #repeating b 
cyclic #c 

i tak dalej ..

wypróbowano:

perl -nle 'print if m/^([a-z])[^$1]+$1[^$1]+$1$/i' </usr/share/dict/web2 

ale nie działa.

Odpowiedz

6
(?:(?!STRING).) 

jest

(?:STRING) 

jak

[^CHAR] 

jest

CHAR 

więc można używać

/ 
^
    (\pL) 
    (?: 
     (?:(?!\1).)+ 
     \1 
    ){2} 
    \z 
/sx 
3

Jest to najlepszy regex mogę wymyślić:

^([a-z])((?:(?!\1).)+\1){2}$ 

Testowane na RegexPal.

0

Można również użyć kwantyfikator leniwy atomowej z grupy non-Backtracking:

^(\w)(?>\w*?\1){2}$ 

chociaż, że działa tylko gdy 0 znaków pośrednich jest dopuszczalne.

z co najmniej 1 znak, że trzeba użyć negatywny uprzedzona:

^(\w)(?>(?!\1)\w+?\1){2}$ 
0

W perlretut mówi, że można wsteczne w regex (nie w prawej części taktycznej) używając \g1. Zostało to zmienione w 5.14. Ponieważ mam tutaj tylko 5.12.2, muszę zamiast tego użyć \1.

Dlatego oryginalny regex z maleńkim adjustion pracował dla mnie:

use strict; use warnings; 
use 5.12.2; 
use feature qw(say); 
for (qw/ azalea baobab cyclic deadend teeeeeestest doesnotwork /) { 
    say if m/^([a-z])[^\1]+\1[^\1]+\1$/i; 
} 

Patrząc na to z YAPE::Regex::Explain

use YAPE::Regex::Explain; 
print YAPE::Regex::Explain->new(qr/^([a-z])[^\1]+\1[^\1]+\1$/i)->explain(); 

plonów:

The regular expression: 

(?i-msx:^([a-z])[^\1]+\1[^\1]+\1$) 

matches as follows: 


use YAPE::Regex::Explain; 
print YAPE::Regex::Explain->new(qr/^([a-z])[^\1]+\1[^\1]+\1$/i)->explain(); 

NODE      EXPLANATION 
---------------------------------------------------------------------- 
(?i-msx:     group, but do not capture (case-insensitive) 
         (with^and $ matching normally) (with . not 
         matching \n) (matching whitespace and # 
         normally): 
---------------------------------------------------------------------- 
^      the beginning of the string 
---------------------------------------------------------------------- 
    (      group and capture to \1: 
---------------------------------------------------------------------- 
    [a-z]     any character of: 'a' to 'z' 
---------------------------------------------------------------------- 
)      end of \1 
---------------------------------------------------------------------- 
    [^\1]+     any character except: '\1' (1 or more 
          times (matching the most amount possible)) 
---------------------------------------------------------------------- 
    \1      what was matched by capture \1 
---------------------------------------------------------------------- 
    [^\1]+     any character except: '\1' (1 or more 
          times (matching the most amount possible)) 
---------------------------------------------------------------------- 
    \1      what was matched by capture \1 
---------------------------------------------------------------------- 
    $      before an optional \n, and the end of the 
          string 
---------------------------------------------------------------------- 
)      end of grouping 
---------------------------------------------------------------------- 

Edit: Twój zatem jeden liniowiec to perl -e 'print if m/^([a-z])[^\1]+\1[^\1]+\1$/i'.

Na innym uwaga, jeśli próbowali perl -w -e 'print if m/(as)$1/' ty natychmiast bym nie widział problemu:

$ perl -w -e 'print if m/(a)$1/' asdf 
Use of uninitialized value $1 in regexp compilation at -e line 1. 
Use of uninitialized value $_ in pattern match (m//) at -e line 1. 

Co ja nie zorientowali się, dlatego pasuje ololololo.

Powiązane problemy