Membuat Regex Dapat Dipertahankan
Kemajuan besar menuju demistifikasi pola yang sebelumnya disebut sebagai "ekspresi reguler" adalah /xbendera regex Perl - terkadang ditulis (?x)ketika disematkan - yang memungkinkan spasi putih (pemutusan baris, indentasi) dan komentar. Ini secara serius meningkatkan keterbacaan dan karenanya pemeliharaan. Ruang putih memungkinkan untuk chunking kognitif, sehingga Anda dapat melihat kelompok apa dengan apa.
Pola-pola modern sekarang juga mendukung referensi yang relatif bernomor dan dinamai sekarang. Itu berarti Anda tidak lagi perlu menghitung kelompok tangkap untuk mengetahui bahwa Anda membutuhkan $4atau \7. Ini membantu saat membuat pola yang dapat dimasukkan dalam pola selanjutnya.
Ini adalah contoh kelompok penangkapan yang relatif bernomor:
$ dupword = qr {\ b (?: (\ w +) (?: \ s + \ g {-1}) +) \ b} xi;
$ dikutip = qr {(["']) $ dupword \ 1} x;
Dan di sini adalah contoh dari pendekatan superior dari tangkapan bernama:
$dupword = qr{ \b (?: (?<word> \w+ ) (?: \s+ \k<word> )+ ) \b }xi;
$quoted = qr{ (?<quote> ["'] ) $dupword \g{quote} }x;
Regex Tata Bahasa
Yang terbaik dari semuanya , tangkapan yang dinamai ini dapat ditempatkan di dalam satu (?(DEFINE)...)blok, sehingga Anda dapat memisahkan deklarasi dari eksekusi elemen-elemen yang disebut individual dari pola Anda. Ini membuat mereka bertindak seperti subrutin dalam pola.
Contoh yang bagus dari "regex gramatikal" semacam ini dapat ditemukan dalam jawaban ini dan yang ini . Ini lebih mirip deklarasi gramatikal.
Saat yang terakhir mengingatkan Anda:
... pastikan untuk tidak menulis pola derau baris. Anda tidak harus, dan Anda seharusnya tidak. Tidak ada bahasa pemrograman yang dapat dipertahankan yang melarang ruang putih, komentar, subrutin, atau pengidentifikasi alfanumerik. Jadi gunakan semua hal itu dalam pola Anda.
Ini tidak bisa terlalu ditekankan. Tentu saja jika Anda tidak menggunakan hal-hal itu dalam pola Anda, Anda akan sering membuat mimpi buruk. Tapi jika Anda lakukan menggunakan mereka, meskipun, Anda tidak perlu.
Berikut adalah contoh lain dari pola tata bahasa modern, yang ini untuk parsing RFC 5322: gunakan 5.10.0;
$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;
Bukankah itu luar biasa - dan indah? Anda dapat menggunakan tata bahasa gaya BNF dan menerjemahkannya langsung ke dalam kode tanpa kehilangan struktur dasarnya!
Jika pola tata bahasa modern masih belum cukup bagi Anda, maka modul brilian Damian ConwayRegexp::Grammars menawarkan sintaks yang lebih bersih, dengan debugging yang unggul juga. Berikut kode yang sama untuk mem-parsing RFC 5322 menyusun kembali ke dalam pola dari modul itu:
#!/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
}
}
Ada banyak hal yang baik di dalam perlre manualnya , tapi ini perbaikan dramatis dalam fitur desain regex mendasar adalah tidak berarti terbatas pada Perl saja. Memang yang pcrepattern manualnya mungkin menjadi membaca lebih mudah, dan mencakup wilayah yang sama.
Pola modern hampir tidak memiliki kesamaan dengan hal-hal primitif yang Anda ajarkan di kelas automata terbatas Anda.