Jak pisać czytelne regexpy
Regexpy słyną z bycia językiem “tylko do zapisu”, często ciężko jest odcyfrować co autor regexpa miał na myśli. Jest (w perlowych i kompatybilnych) pewien ficzer który to ułatwia, mianowicie opcja x
, powoduje ona że parser regexpów ignoruje komentarze, czyli taki np. dekoder daty (tak wiem że są liby, to tylko przykład ;))
my ($year, $mon, $mday, $hour, $min, $sec) = $date =~ /(\d{1,4})\-(\d{1,2})\-(\d{1,2})\s+(\d{1,2})\:(\d{1,2})\:(\d{1,2}).*/; |
można zapisać w formie:
my ($year, $mon, $mday, $hour, $min, $sec) = $date =~ /(\d{1,4})\- # year- (\d{1,2})\- # month- (\d{1,2})\s+ # day + whitespace (\d{1,2})\: # hour: (\d{1,2})\: # min: (\d{1,2}) # sec: .* #rest of crap /x; |
Trzeba tylko “wyescapować” wszystkie spacje (chociażby przez \s
co oznacza “any whitespace” czyli też taby i \n
)
Z innych przydatnych rzeczy to ściąga i edytor z tych “mniej znanych a przydatnych” :
(?:...)
– pasywna grupa tzn matchuje ale nie będzie zwracane do zmiennych, czyli np(?:foo|bar)(.*)
zwróci w zmiennej tylko zawartość bloku(.*)
a nie foo/bar\s
i pokrewne, zamiast pisać\
(backslash spacja) czytelniej jest użyć\s
które dodatkowo zmatchuje nam też taby i pare innych niewidocznych znaczków.\s+
jest przydatne, “matchuj jeden lub więcej whitespace”{x,y}
– zmatchuj od x do y znaków – np \d{3,} – więcej niż 3 cyfry, \S{5,9} – od 5 do 9 “nie-whitespace”?
– powoduje że match będzie “ungreedy” czyli “zmatchuj minimalną liczbę znaków która będzie pasować, np gdy wrzucimy ciąg znaków “a:b:c” do regexpa(.*)\:(.*)
to dostaniemy matche ‘a:b’ i ‘c’, gdy zrobimy matcha(.*?)\:(.*)
na tym samym tekście to wynikiem będzie ‘a’ i ‘b:c’
Inną metodą na tworzenie regexpów jest “pokaż swojemu kotu jaki tekst chcesz zmatchować a potem posadź go na klawiaturze” ale to troszeczkę mniej czytelne ;]