Powiedzmy:
/(a|b)/
vs /[ab]/
Odpowiedzi:
19 dla odpowiedzi nr 1W powyższym przykładzie nie ma dużej różnicy (w większości języków). Główną różnicą jest to, że ()
wersja tworzy grupę, do której można odwoływać się ponownie 1
w meczu (lub czasami $1
). The []
wersja tego nie robi.
Również,
/(ab|cd)/ # matches "ab" or "cd"
/[abcd]/ # matches "a", "b", "c" or "d"
6 dla odpowiedzi nr 2
()
w wyrażeniu regularnym służy do grupowania wyrażeń regularnych, umożliwiając zastosowanie operatorów do całego wyrażenia zamiast do pojedynczego znaku. Na przykład, jeśli mam wyrażenie regularne ab
, następnie ab*
odnosi się do a
po którym następuje dowolna liczba b
s (na przykład a
, ab
, abb
itp.), podczas gdy (ab)*
odnosi się do dowolnej liczby powtórzeń sekwencji ab
(na przykład pusty ciąg, ab
, abab
itp.). W wielu silnikach wyrażeń regularnych ()
są również używane do tworzenia referencji, do których można się odwoływać po dopasowaniu. Na przykład w Ruby po wykonaniu "foo" =~ /f(o*)/
, $1
będzie zawierać oo
.
|
w wyrażeniu regularnym wskazuje na przemian; oznacza wyrażenie przed taktem lub wyrażenie po nim. Możesz dopasować dowolną cyfrę do wyrażenia 0|1|2|3|4|5|6|7|8|9
. Często zobaczysz zapakowane naprzemienniezestaw nawiasów w celu grupowania lub przechwytywania podwyrażenia, ale nie jest to wymagane. Możesz używać naprzemiennie również w przypadku dłuższych wyrażeń, takich jak foo|bar
, aby wskazać albo foo
lub bar
.
Możesz wyrazić każde wyrażenie regularne (w sensie formalnym, teoretycznym, a nie rozszerzonym, z którego korzysta wiele języków), tylko z naprzemienną zmianą |
, zamknięcie kleene *
, konkatenacja (tylko napisanie dwóch wyrażeńobok siebie bez żadnych odstępów) oraz nawiasy do grupowania. Byłoby to jednak raczej niewygodne w przypadku skomplikowanych wyrażeń, dlatego powszechnie dostępnych jest kilka skrótów. Na przykład, x?
jest tylko skrótem dla |x
(to znaczy pusty ciąg znaków lub x
), podczas y+
jest skrótem dla yy*
.
[]
są w zasadzie skrótem dla przemienności |
wszystkich znaków lub zakresów znaków w nim zawartych. Tak jak powiedziałem, mógłbym pisać 0|1|3|4|5|6|7|8|9
, ale o wiele wygodniej jest pisać [0-9]
. Mogę też pisać [a-zA-Z]
reprezentować dowolny list. Zauważ, że podczas []
zapewniają grupowanie, zasadniczo nie wprowadzają nowego odniesienia, do którego można będzie się później odwoływać; w tym celu musicie owinąć je w nawiasy ([a-zA-Z])
Zatem dwa przykładowe wyrażenia regularne są równoważne pod względem dopasowania, ale (a|b)
ustawi pierwsze podpasowanie dla pasującego znaku, natomiast [ab]
nie utworzy żadnych odniesień do pod-meczów.
5 dla odpowiedzi nr 3
Po pierwsze, gdy mówimy o wyrażeniach regularnych, to częstoważne, aby określić, o jakich wyrażeniach regularnych mówisz. Istnieje kilka odmian (takich jak tradycyjne wyrażenia regularne POSIX, wyrażenia regularne zgodne z Perl i Perl (PCRE) itp.).
Zakładając PCRE lub coś bardzo podobnego, co często jest obecnie najbardziej powszechne, istnieją trzy kluczowe różnice:
- Korzystając z grup w nawiasach, możesz sprawdzić opcje składające się z więcej niż jednego znaku. Więc / (a | b) / może zamiast tego być / (abc | defg) /.
- Grupy w nawiasach wykonują operację przechwytywaniaabyś mógł wyodrębnić wynik (aby dopasować go do „b”, możesz odzyskać „b” i zobaczyć to). / [ab] / nie. Operację przechwytywania można zastąpić dodając?: Like so: / (?: a | b) /
- Nawet jeśli zastąpisz zachowanie przechwytywaniaw nawiasach podstawowa implementacja może być jeszcze szybsza w przypadku [] podczas sprawdzania pojedynczych znaków (chociaż nic nie mówi, że nie przechwytywanie (?: a | b) nie może być zoptymalizowane jako specjalny przypadek do [ab], ale kompilacja wyrażeń regularnych może potrwać nawet nieco dłużej).