Regexes'i Bakım Yapabilme
Daha önce “düzenli ifadeler” olarak adlandırılan örüntüleri belirsizleştirmeye yönelik büyük bir ilerleme Perl's /x
bazen (?x)
gömüldüğünde yazılan ve boşluk (satır kesmesi, girintileme) ve yorumlara izin veren işaretidir. Bu, okunabilirliği ve dolayısıyla sürdürülebilirliği ciddi şekilde geliştirir. Beyaz boşluk bilişsel parçalamaya izin verir, böylece hangi grupların neyle birlikte olduğunu görebilirsiniz.
Modern kalıplar artık hem nispeten sayılı hem de adlandırılmış geri başvuruları desteklemektedir. Bu, ihtiyacınız olduğunu anlamak için artık yakalama gruplarını saymanıza gerek olmadığı anlamına gelir$4
veya \7
. Bu, diğer kalıplara eklenebilecek kalıplar oluştururken yardımcı olur.
Göreceli olarak numaralandırılmış bir yakalama grubuna örnek:
$ dupword = qr {\ b (?: (\ w +) (?: \ s + \ g {-1}) +) \ b} xi;
$ quoted = qr {(["']) $ dupword \ 1} x;
Ve burada adlandırılmış yakalamaların üstün yaklaşımının bir örneği:
$dupword = qr{ \b (?: (?<word> \w+ ) (?: \s+ \k<word> )+ ) \b }xi;
$quoted = qr{ (?<quote> ["'] ) $dupword \g{quote} }x;
Dilbilgisel Düzenlemeler
Hepsinden iyisi , bu adlandırılmış yakalamalar bir (?(DEFINE)...)
blok içine yerleştirilebilir , böylece bildirimi kalıplarınızın tek tek adlandırılmış öğelerinin yürütülmesinden ayırabilirsiniz. Bu onları kalıptaki alt rutinler gibi hareket ettirir.
Bu tür “dilbilgisel regex” in iyi bir örneği bu cevapta ve bu cevapta bulunabilir . Bunlar daha çok gramer bildirisine benziyor.
İkincisinin size hatırlattığı gibi:
… Hiçbir zaman çizgi gürültüsü kalıpları yazmadığınızdan emin olun. Gerek yok ve gerek yok. Beyaz boşluk, yorumlar, alt rutinler veya alfasayısal tanımlayıcıları yasaklayan hiçbir programlama dili korunamaz. Öyleyse kalıplarınızdaki tüm bunları kullanın.
Bu fazla vurgulanamaz. Elbette bu şeyleri desenlerinizde kullanmazsanız, genellikle bir kabus yaratacaksınız. Eğer Ama eğer yapmak bunları kullanmak olsa da, sen gerekmez.
İşte modern bir gramer deseninin başka bir örneği, bu RFC 5322'yi ayrıştırmak için: 5.10.0 kullanın;
$rfc5322 = qr{
(?(DEFINE)
(?<address> (?&mailbox) | (?&group))
(?<mailbox> (?&name_addr) | (?&addr_spec))
(?<name_addr> (?&display_name)? (?&angle_addr))
(?<angle_addr> (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
(?<group> (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ; (?&CFWS)?)
(?<display_name> (?&phrase))
(?<mailbox_list> (?&mailbox) (?: , (?&mailbox))*)
(?<addr_spec> (?&local_part) \@ (?&domain))
(?<local_part> (?&dot_atom) | (?"ed_string))
(?<domain> (?&dot_atom) | (?&domain_literal))
(?<domain_literal> (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
\] (?&CFWS)?)
(?<dcontent> (?&dtext) | (?"ed_pair))
(?<dtext> (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])
(?<atext> (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
(?<atom> (?&CFWS)? (?&atext)+ (?&CFWS)?)
(?<dot_atom> (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
(?<dot_atom_text> (?&atext)+ (?: \. (?&atext)+)*)
(?<text> [\x01-\x09\x0b\x0c\x0e-\x7f])
(?<quoted_pair> \\ (?&text))
(?<qtext> (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
(?<qcontent> (?&qtext) | (?"ed_pair))
(?<quoted_string> (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
(?&FWS)? (?&DQUOTE) (?&CFWS)?)
(?<word> (?&atom) | (?"ed_string))
(?<phrase> (?&word)+)
# Folding white space
(?<FWS> (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
(?<ctext> (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
(?<ccontent> (?&ctext) | (?"ed_pair) | (?&comment))
(?<comment> \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
(?<CFWS> (?: (?&FWS)? (?&comment))*
(?: (?:(?&FWS)? (?&comment)) | (?&FWS)))
# No whitespace control
(?<NO_WS_CTL> [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])
(?<ALPHA> [A-Za-z])
(?<DIGIT> [0-9])
(?<CRLF> \x0d \x0a)
(?<DQUOTE> ")
(?<WSP> [\x20\x09])
)
(?&address)
}x;
Bu olağanüstü ve muhteşem değil mi? BNF tarzı bir dilbilgisi alabilir ve temel yapısını kaybetmeden doğrudan koda çevirebilirsiniz!
Modern gramer desenleri hala sizin için yeterli değilse Damian Conway'in parlak Regexp::Grammars
modülü , daha üstün hata ayıklama ile daha da temiz bir sözdizimi sunar. RFC 5322 recast'ı bu modüldeki bir desene ayrıştırmak için aynı kod:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Data::Dumper "Dumper";
my $rfc5322 = do {
use Regexp::Grammars; # ...the magic is lexically scoped
qr{
# Keep the big stick handy, just in case...
# <debug:on>
# Match this...
<address>
# As defined by these...
<token: address> <mailbox> | <group>
<token: mailbox> <name_addr> | <addr_spec>
<token: name_addr> <display_name>? <angle_addr>
<token: angle_addr> <CFWS>? \< <addr_spec> \> <CFWS>?
<token: group> <display_name> : (?:<mailbox_list> | <CFWS>)? ; <CFWS>?
<token: display_name> <phrase>
<token: mailbox_list> <[mailbox]> ** (,)
<token: addr_spec> <local_part> \@ <domain>
<token: local_part> <dot_atom> | <quoted_string>
<token: domain> <dot_atom> | <domain_literal>
<token: domain_literal> <CFWS>? \[ (?: <FWS>? <[dcontent]>)* <FWS>?
<token: dcontent> <dtext> | <quoted_pair>
<token: dtext> <.NO_WS_CTL> | [\x21-\x5a\x5e-\x7e]
<token: atext> <.ALPHA> | <.DIGIT> | [!#\$%&'*+-/=?^_`{|}~]
<token: atom> <.CFWS>? <.atext>+ <.CFWS>?
<token: dot_atom> <.CFWS>? <.dot_atom_text> <.CFWS>?
<token: dot_atom> <.CFWS>? <.dot_atom_text> <.CFWS>?
<token: dot_atom_text> <.atext>+ (?: \. <.atext>+)*
<token: text> [\x01-\x09\x0b\x0c\x0e-\x7f]
<token: quoted_pair> \\ <.text>
<token: qtext> <.NO_WS_CTL> | [\x21\x23-\x5b\x5d-\x7e]
<token: qcontent> <.qtext> | <.quoted_pair>
<token: quoted_string> <.CFWS>? <.DQUOTE> (?:<.FWS>? <.qcontent>)*
<.FWS>? <.DQUOTE> <.CFWS>?
<token: word> <.atom> | <.quoted_string>
<token: phrase> <.word>+
# Folding white space
<token: FWS> (?: <.WSP>* <.CRLF>)? <.WSP>+
<token: ctext> <.NO_WS_CTL> | [\x21-\x27\x2a-\x5b\x5d-\x7e]
<token: ccontent> <.ctext> | <.quoted_pair> | <.comment>
<token: comment> \( (?: <.FWS>? <.ccontent>)* <.FWS>? \)
<token: CFWS> (?: <.FWS>? <.comment>)*
(?: (?:<.FWS>? <.comment>) | <.FWS>)
# No whitespace control
<token: NO_WS_CTL> [\x01-\x08\x0b\x0c\x0e-\x1f\x7f]
<token: ALPHA> [A-Za-z]
<token: DIGIT> [0-9]
<token: CRLF> \x0d \x0a
<token: DQUOTE> "
<token: WSP> [\x20\x09]
}x;
};
while (my $input = <>) {
if ($input =~ $rfc5322) {
say Dumper \%/; # ...the parse tree of any successful match
# appears in this punctuation variable
}
}
Orada iyi bir sürü şey var perlre manpage ama temel regex tasarım özellikleri bu dramatik gelişmeler yalnız Perl ile sınırlı değillerdir. Gerçekten de pcrepattern manpage daha kolay okunabilir ve aynı bölgeyi kapsıyor olabilir.
Modern kalıpların, sonlu otomata sınıfınızda öğretilen ilkel şeylerle neredeyse hiçbir ortak yanı yoktur.