InggrisPerancisSpanyol

favorit OnWorks

perlretut - Daring di Awan

Jalankan perlretut di penyedia hosting gratis OnWorks melalui Ubuntu Online, Fedora Online, emulator online Windows atau emulator online MAC OS

Ini adalah perintah perlretut yang dapat dijalankan di penyedia hosting gratis OnWorks menggunakan salah satu dari beberapa workstation online gratis kami seperti Ubuntu Online, Fedora Online, emulator online Windows atau emulator online MAC OS

PROGRAM:

NAMA


perlretut - tutorial ekspresi reguler Perl

DESKRIPSI


Halaman ini memberikan tutorial dasar tentang memahami, membuat, dan menggunakan reguler
ekspresi dalam Perl. Ini berfungsi sebagai pelengkap halaman referensi reguler
ekspresi perlre. Ekspresi reguler merupakan bagian integral dari "m//", "s///", "qr//"
dan operator "split" sehingga tutorial ini juga tumpang tindih dengan "Regexp Quote-Like
Operator" di perlop dan "split" di perlfunc.

Perl secara luas terkenal karena keunggulan dalam pemrosesan teks, dan ekspresi reguler adalah salah satunya
faktor besar di balik ketenaran ini. Ekspresi reguler Perl menampilkan efisiensi dan
fleksibilitas tidak diketahui di sebagian besar bahasa komputer lainnya. Menguasai bahkan dasar-dasar
ekspresi reguler akan memungkinkan Anda untuk memanipulasi teks dengan sangat mudah.

Apa itu ekspresi reguler? Ekspresi reguler hanyalah string yang menggambarkan a
pola. Pola umum digunakan akhir-akhir ini; contohnya adalah pola yang diketik menjadi a
mesin pencari untuk menemukan halaman web dan pola yang digunakan untuk membuat daftar file dalam direktori, misalnya,
"ls *.txt" atau "dir *.*". Di Perl, pola yang dijelaskan oleh ekspresi reguler digunakan
untuk mencari string, mengekstrak bagian string yang diinginkan, dan melakukan pencarian dan penggantian
operasi.

Ekspresi reguler memiliki reputasi abstrak dan sulit untuk
memahami. Ekspresi reguler dibangun menggunakan konsep sederhana seperti conditional
dan loop dan tidak lebih sulit untuk dipahami daripada kondisional "jika" yang sesuai
dan loop "sementara" dalam bahasa Perl itu sendiri. Padahal, tantangan utama dalam belajar
ekspresi reguler baru saja terbiasa dengan notasi singkat yang digunakan untuk mengekspresikan ini
konsep.

Tutorial ini meratakan kurva belajar dengan membahas konsep ekspresi reguler, bersama
dengan notasi mereka, satu per satu dan dengan banyak contoh. Bagian pertama dari tutorial
akan berkembang dari pencarian kata paling sederhana ke konsep ekspresi reguler dasar.
Jika Anda menguasai bagian pertama, Anda akan memiliki semua alat yang diperlukan untuk menyelesaikan sekitar 98% dari
kebutuhanmu. Bagian kedua dari tutorial ini adalah untuk mereka yang nyaman dengan dasar-dasarnya dan
haus akan lebih banyak alat-alat listrik. Ini membahas operator ekspresi reguler yang lebih maju
dan memperkenalkan inovasi mutakhir terbaru.

Catatan: untuk menghemat waktu, 'regular expression' sering disingkat regexp atau regex.
Regexp adalah singkatan yang lebih alami daripada regex, tetapi lebih sulit untuk diucapkan. Perl
dokumentasi pod dibagi secara merata pada regexp vs regex; di Perl, ada lebih dari satu cara
untuk menyingkatnya. Kami akan menggunakan regexp dalam tutorial ini.

Baru di v5.22, "use re 'strict'" menerapkan aturan yang lebih ketat daripada yang lain saat kompilasi
pola ekspresi reguler. Ia dapat menemukan hal-hal yang, meskipun legal, mungkin tidak sesuai dengan keinginan Anda
dimaksudkan.

Bagian 1: dasar-dasar


Sederhana kata sesuai
Regexp paling sederhana hanyalah sebuah kata, atau lebih umum, serangkaian karakter. Sebuah regexp
terdiri dari kata yang cocok dengan string apa pun yang berisi kata itu:

"Halo Dunia" =~ /Dunia/; # pertandingan

Tentang apa pernyataan Perl ini? "Hello World" adalah string sederhana yang dikutip ganda.
"Dunia" adalah ekspresi reguler dan "//" melampirkan "/ Dunia/" memberitahu Perl untuk mencari
string untuk pertandingan. Operator "=~" mengaitkan string dengan kecocokan regexp dan
menghasilkan nilai true jika regexp cocok, atau false jika regexp tidak cocok. di kami
kasus, "Dunia" cocok dengan kata kedua dalam "Halo Dunia", jadi ekspresinya benar.
Ekspresi seperti ini berguna dalam conditional:

if ("Halo Dunia" =~ /Dunia/) {
print "Ini cocok\n";
}
else {
print "Tidak cocok\n";
}

Ada variasi yang berguna pada tema ini. Rasa kecocokan dapat dibalik dengan
menggunakan operator "!~":

if ("Halo Dunia" !~ /Dunia/) {
print "Tidak cocok\n";
}
else {
print "Ini cocok\n";
}

String literal dalam regexp dapat diganti dengan variabel:

$salam = "Dunia";
if ("Halo Dunia" =~ /$salam/) {
print "Ini cocok\n";
}
else {
print "Tidak cocok\n";
}

Jika Anda mencocokkan dengan variabel default khusus $_, bagian "$_ =~" dapat menjadi
dihilangkan:

$_ = "Halo Dunia";
jika (/Dunia/) {
print "Ini cocok\n";
}
else {
print "Tidak cocok\n";
}

Dan akhirnya, pembatas default "//" untuk pertandingan dapat diubah menjadi sewenang-wenang
pembatas dengan meletakkan 'm' di depan:

"Halo Dunia" =~ m!Dunia!; # kecocokan, dipisahkan dengan '!'
"Halo Dunia" =~ m{Dunia}; # cocok, perhatikan '{}' yang cocok
"/usr/bin/Perl" =~ m"/perl"; # cocok setelah '/ usr / bin',
# '/' menjadi karakter biasa

"/Dunia/", "m!Dunia!", dan "m{Dunia}" semuanya mewakili hal yang sama. Kapan, misalnya, kutipan
(""") digunakan sebagai pembatas, garis miring '/' menjadi karakter biasa dan dapat
digunakan dalam regexp ini tanpa masalah.

Mari kita pertimbangkan bagaimana regexp yang berbeda akan cocok dengan "Hello World":

"Halo Dunia" =~ /dunia/; # tidak cocok
"Halo Dunia" =~ /o W/; # pertandingan
"Halo Dunia" =~ /oW/; # tidak cocok
"Halo Dunia" =~ /Dunia /; # tidak cocok

Regexp "dunia" pertama tidak cocok karena regexp peka huruf besar/kecil. Kedua
regexp cocok karena substring 'o W' muncul di string "Hello World". Ruang angkasa
karakter ' ' diperlakukan seperti karakter lain dalam regexp dan diperlukan untuk mencocokkan dalam
kasus ini. Kurangnya karakter spasi adalah alasan regexp ketiga 'oW' tidak
cocok. Regexp keempat 'Dunia' tidak cocok karena ada spasi di akhir
regexp, tetapi tidak di akhir string. Pelajaran di sini adalah bahwa regexps harus cocok
bagian dari tali persis agar pernyataan tersebut benar.

Jika sebuah regexp cocok di lebih dari satu tempat dalam string, Perl akan selalu cocok di
titik sedini mungkin dalam string:

"Halo Dunia" =~ /o/; # cocok dengan 'o' di 'Halo'
"Topi itu berwarna merah" =~ /hat/; # cocok dengan 'topi' di 'Itu'

Sehubungan dengan pencocokan karakter, ada beberapa poin lagi yang perlu Anda ketahui.
Pertama-tama, tidak semua karakter dapat digunakan 'apa adanya' dalam pertandingan. Beberapa karakter, disebut
karakter meta, dicadangkan untuk digunakan dalam notasi regexp. Metakarakter tersebut adalah

{}[]()^$.|*+?\

Arti penting dari masing-masing akan dijelaskan di sisa tutorial, tetapi untuk
sekarang, penting hanya untuk mengetahui bahwa metakarakter dapat dicocokkan dengan meletakkan a
garis miring terbalik sebelumnya:

"2+2=4" =~ /2+2/; # tidak cocok, + adalah metakarakter
"2+2=4" =~ /2\+2/; # cocok, \+ diperlakukan seperti + . biasa
"Intervalnya adalah [0,1)." =~ /[0,1)./ # adalah kesalahan sintaks!
"Intervalnya adalah [0,1)." =~ /\[0,1\)\./ # cocok
"#!/usr/bin/Perl" =~ /#!\/ usr\/tempat sampah\/perl/; # pertandingan

Pada regexp terakhir, garis miring '/' juga menjadi garis miring terbalik, karena digunakan untuk
batasi regexp. Namun, ini dapat menyebabkan LTS (sindrom tusuk gigi miring), dan itu adalah
sering lebih mudah dibaca untuk mengubah pembatas.

"#!/usr/bin/Perl" =~ m!#\!/usr/bin/Perl!; # lebih mudah dibaca

Karakter garis miring terbalik '\' adalah karakter meta itu sendiri dan perlu dibuat garis miring terbalik:

'C:\WIN32' =~ /C:\\WIN/; # pertandingan

Selain karakter meta, ada beberapa karakter ASCII yang tidak memiliki
setara karakter yang dapat dicetak dan sebaliknya diwakili oleh melarikan diri urutan. Umum
contohnya adalah "\t" untuk tab, "\n" untuk baris baru, "\r" untuk carriage return dan "\a" untuk a
bel (atau peringatan). Jika string Anda lebih baik dianggap sebagai urutan byte arbitrer,
urutan escape oktal, misalnya, "\033", atau urutan escape heksadesimal, misalnya, "\x1B" mungkin
menjadi representasi yang lebih alami untuk byte Anda. Berikut adalah beberapa contoh pelarian:

"1000\t2000" =~ m(0\t2) # cocok
"1000\n2000" =~ /0\n20/ # cocok
"1000\t2000" =~ /\000\t2/ # tidak cocok, "0" ne "\000"
"cat" =~ /\o{143}\x61\x74/ # cocok dengan ASCII, tetapi cara yang aneh
# untuk mengeja kucing

Jika Anda sudah lama berada di sekitar Perl, semua pembicaraan tentang urutan pelarian ini mungkin tampak familier.
Urutan pelarian serupa digunakan dalam string yang dikutip ganda dan sebenarnya regexps di Perl
sebagian besar diperlakukan sebagai string yang dikutip ganda. Ini berarti bahwa variabel dapat digunakan dalam
regexp juga. Sama seperti string yang dikutip ganda, nilai-nilai variabel dalam
regexp akan diganti sebelum regexp dievaluasi untuk tujuan yang cocok. Jadi kita
memiliki:

$foo = 'rumah';
'kucing rumah' =~ /$foo/; # pertandingan
'cathouse' =~ /cat$foo/; # pertandingan
'housecat' =~ /${foo}cat/; # pertandingan

Sejauh ini baik. Dengan pengetahuan di atas Anda sudah dapat melakukan pencarian hanya dengan
tentang regexp string literal apa pun yang dapat Anda impikan. Ini adalah sangat sederhana emulasi dari
Program grep Unix:

% kucing > simple_grep
#!/usr/bin/Perl
$regexp = pergeseran;
sementara (<>) {
cetak jika /$regexp/;
}
^D

% chmod +x simple_grep

% simple_grep di /usr/dict/words
Babbage
kubis
kubis
Sabat
Sabat
Sabat
cuti panjang
sarung
sarung

Program ini mudah dipahami. "#!/usr/bin/Perl" adalah cara standar untuk memanggil a
program perl dari shell. "$regexp = shift;" menyimpan argumen baris perintah pertama sebagai
regexp yang akan digunakan, membiarkan argumen baris perintah lainnya diperlakukan sebagai
file. " while (<>)" mengulang semua baris di semua file. Untuk setiap baris,
"cetak jika /$regexp/;" mencetak baris jika regexp cocok dengan baris. Di baris ini, keduanya
"print" dan "/$regexp/" menggunakan variabel default $_ secara implisit.

Dengan semua regexp di atas, jika regexp cocok di mana saja dalam string, itu adalah
dianggap cocok. Namun, terkadang kami ingin menentukan dimana dalam string itu
regexp harus mencoba mencocokkan. Untuk melakukan ini, kita akan menggunakan jangkar metakarakter "^" dan
"$". Jangkar "^" berarti kecocokan di awal string dan jangkar "$" berarti
cocok di akhir string, atau sebelum baris baru di akhir string. Begini caranya
mereka digunakan:

"pembantu rumah tangga" =~ /penjaga/; # pertandingan
"pembantu rumah tangga" =~ /^penjaga/; # tidak cocok
"pembantu rumah tangga" =~ /keeper$/; # pertandingan
"pengurus rumah\n" =~ /keeper$/; # pertandingan

Regexp kedua tidak cocok karena "^" membatasi "penjaga" untuk mencocokkan hanya di
awal string, tapi "housekeeper" memiliki penjaga mulai di tengah. Ketiga
regexp cocok, karena "$" membatasi "penjaga" untuk mencocokkan hanya di akhir
String.

Ketika "^" dan "$" digunakan secara bersamaan, regexp harus cocok dengan keduanya
awal dan akhir string, yaitu, regexp cocok dengan seluruh string. Mempertimbangkan

"penjaga" =~ /^keep$/; # tidak cocok
"penjaga" =~ /^penjaga$/; # pertandingan
"" =~ /^$/; # ^$ cocok dengan string kosong

Regexp pertama tidak cocok karena string memiliki lebih dari "keep". Sejak
regexp kedua persis string, cocok. Menggunakan "^" dan "$" di regexp
memaksa string lengkap untuk dicocokkan, sehingga memberi Anda kontrol penuh atas string mana
cocok dan mana yang tidak. Misalkan Anda mencari sesama bernama bert, off in a string
sendiri:

"dogbert" =~ /bert/; # cocok, tetapi bukan yang Anda inginkan

"dilbert" =~ /^bert/; # tidak cocok, tapi ..
"bertram" =~ /^bert/; # cocok, jadi masih belum cukup bagus

"bertram" =~ /^bert$/; # tidak cocok, bagus
"dilbert" =~ /^bert$/; # tidak cocok, bagus
"bert" =~ /^bert$/; # cocok, sempurna

Tentu saja, dalam kasus string literal, seseorang dapat dengan mudah menggunakan string
perbandingan "$string eq 'bert'" dan itu akan lebih efisien. Regexp "^...$"
benar-benar menjadi berguna ketika kami menambahkan alat regexp yang lebih kuat di bawah ini.

Menggunakan karakter kelas-kelas
Meskipun seseorang sudah dapat melakukan cukup banyak dengan regexp string literal di atas, kami hanya
menggores permukaan teknologi ekspresi reguler. Di bagian ini dan selanjutnya
kami akan memperkenalkan konsep regexp (dan notasi metakarakter terkait) yang memungkinkan
sebuah regexp untuk mewakili tidak hanya urutan karakter tunggal, tetapi a seluruh kelas dari mereka.

Salah satu konsep tersebut adalah karakter kelas. Kelas karakter memungkinkan serangkaian kemungkinan
karakter, bukan hanya satu karakter, untuk dicocokkan pada titik tertentu dalam a
reg. Anda dapat menentukan kelas karakter kustom Anda sendiri. Ini dilambangkan dengan tanda kurung
"[...]", dengan set karakter yang mungkin cocok di dalamnya. Berikut adalah beberapa
contoh:

/kucing/; # cocok dengan 'kucing'
/[bcr]di/; # cocok dengan 'kelelawar, 'kucing', atau 'tikus'
/barang[0123456789]/; # cocok dengan 'item0' atau ... atau 'item9'
"abc" =~ /[taksi]/; # cocok dengan 'a'

Dalam pernyataan terakhir, meskipun 'c' adalah karakter pertama di kelas, 'a' cocok
karena posisi karakter pertama dalam string adalah titik paling awal di mana
regexp bisa cocok.

/[yY][eE][sS]/; # cocokkan 'ya' dengan cara yang tidak peka huruf besar-kecil
# 'ya', 'Ya', 'YA', dll.

Regexp ini menampilkan tugas umum: melakukan pencocokan case-insensitive. Perl menyediakan cara
menghindari semua tanda kurung hanya dengan menambahkan 'i' ke akhir pertandingan. Kemudian
"/[yY][eE][sS]/;" dapat ditulis ulang sebagai "/yes/i;". 'i' adalah singkatan dari case-insensitive dan
adalah contoh dari pengubah dari operasi pencocokan. Kita akan bertemu modifikator lain nanti
dalam tutorialnya.

Kami melihat di bagian atas bahwa ada karakter biasa, yang mewakili
diri mereka sendiri, dan karakter khusus, yang membutuhkan garis miring terbalik "\" untuk mewakili diri mereka sendiri.
Hal yang sama berlaku di kelas karakter, tetapi kumpulan karakter biasa dan khusus
di dalam kelas karakter berbeda dengan di luar kelas karakter. yang spesial
karakter untuk kelas karakter adalah "-]\^$" (dan pembatas pola, apa pun itu).
"]" spesial karena menunjukkan akhir dari kelas karakter. "$" spesial karena itu
menunjukkan variabel skalar. "\" istimewa karena digunakan dalam urutan pelarian, hanya
seperti di atas. Berikut adalah bagaimana karakter khusus "]$\" ditangani:

/[\]c]def/; # cocok dengan ']def' atau 'cdef'
$x = 'bcr';
/[$x]di/; # cocok dengan 'kelelawar', 'kucing', atau 'tikus'
/[\$x]di/; # cocok dengan '$at' atau 'xat'
/[\\$x]di/; # cocok dengan '\at', 'kelelawar, 'kucing', atau 'tikus'

Dua yang terakhir sedikit rumit. Dalam "[\$x]", garis miring terbalik melindungi tanda dolar, jadi
kelas karakter memiliki dua anggota "$" dan "x". Dalam "[\\$x]", garis miring terbalik dilindungi,
jadi $x diperlakukan sebagai variabel dan diganti dengan cara kutip ganda.

Karakter khusus '-' bertindak sebagai operator rentang dalam kelas karakter, sehingga a
set karakter yang berdekatan dapat ditulis sebagai rentang. Dengan jangkauan, yang berat
"[0123456789]" dan "[abc...xyz]" menjadi langsing "[0-9]" dan "[az]". Beberapa contohnya adalah

/item[0-9]/; # cocok dengan 'item0' atau ... atau 'item9'
/[0-9bx-z]aa/; # cocok dengan '0aa', ..., '9aa',
# 'baa', 'xaa', 'yaa', atau 'zaa'
/[0-9a-fA-F]/; # cocok dengan digit heksadesimal
/[0-9a-zA-Z_]/; # cocok dengan karakter "kata",
# seperti yang ada di nama variabel Perl

Jika '-' adalah karakter pertama atau terakhir dalam kelas karakter, itu diperlakukan sebagai biasa
karakter; "[-ab]", "[ab-]" ​​dan "[a\-b]" semuanya setara.

Karakter khusus "^" di posisi pertama kelas karakter menunjukkan a dinegasikan
karakter kelas, yang cocok dengan karakter apa pun kecuali yang ada di dalam tanda kurung. Berdua dan
"[^...]" harus cocok dengan karakter, atau kecocokan akan gagal. Kemudian

/[^a]di/; # tidak cocok dengan 'aat' atau 'at', tetapi cocok
# semua 'kelelawar', 'kucing, '0at', '%at', dll.
/[^0-9]/; # cocok dengan karakter non-numerik
/[a^]di/; # cocok dengan 'aat' atau '^at'; di sini '^' biasa saja

Sekarang, bahkan "[0-9]" bisa merepotkan untuk menulis berkali-kali, jadi untuk kepentingan menabung
penekanan tombol dan membuat regexps lebih mudah dibaca, Perl memiliki beberapa singkatan untuk umum
kelas karakter, seperti yang ditunjukkan di bawah ini. Sejak diperkenalkannya Unicode, kecuali "//a"
pengubah berlaku, kelas karakter ini cocok lebih dari hanya beberapa karakter di
kisaran ASCII.

· \d cocok dengan angka, tidak hanya [0-9] tetapi juga angka dari skrip non-romawi

· \s cocok dengan karakter spasi putih, himpunan [\ \t\r\n\f] dan lainnya

· \w cocok dengan karakter kata (alfanumerik atau _), bukan hanya [0-9a-zA-Z_] tetapi juga angka
dan karakter dari skrip non-romawi

· \D adalah \d yang dinegasikan; itu mewakili karakter lain selain digit, atau [^\d]

· \S adalah \s yang dinegasikan; itu mewakili karakter non-spasi [^\s]

· \W adalah \w yang dinegasikan; itu mewakili karakter non-kata apa pun [^\w]

· Periode '.' cocok dengan karakter apa pun kecuali "\n" (kecuali pengubah "//s" berlaku,
seperti yang dijelaskan di bawah).

· \N, seperti titik, cocok dengan karakter apa pun kecuali "\n", tetapi tetap sama terlepas dari
apakah pengubah "//s" berlaku.

Pengubah "//a", tersedia mulai dari Perl 5.14, digunakan untuk membatasi kecocokan
\d, \s, dan \w hanya untuk mereka yang berada dalam rentang ASCII. Hal ini berguna untuk menjaga program Anda dari
diekspos secara tidak perlu ke Unicode penuh (dan pertimbangan keamanan yang menyertainya)
ketika yang Anda inginkan hanyalah memproses teks seperti bahasa Inggris. ("a" dapat digandakan, "//aa", untuk
memberikan lebih banyak batasan, mencegah pencocokan case-insensitive ASCII dengan non-
karakter ASCII; jika tidak, "Tanda Kelvin" Unicode akan cocok dengan "k" atau "K".)

Singkatan "\d\s\w\D\S\W" dapat digunakan baik di dalam maupun di luar tanda kurung
kelas karakter. Berikut beberapa yang digunakan:

/\d\d:\d\d:\d\d/; # cocok dengan format waktu jj:mm:dd
/[\d\s]/; # cocok dengan digit atau karakter spasi apa pun
/\w\W\w/; # cocok dengan kata char, diikuti oleh a
# char non-kata, diikuti oleh kata char
/..rt/; # cocok dengan dua karakter apa pun, diikuti oleh 'rt'
/akhir\./; # cocok dengan 'akhir'.
/akhir[.]/; # hal yang sama, cocok dengan 'akhir'.

Karena titik adalah karakter meta, itu perlu diloloskan agar sesuai dengan yang biasa
Titik. Karena, misalnya, "\d" dan "\w" adalah kumpulan karakter, maka salah untuk
anggap "[^\d\w]" sebagai "[\D\W]"; sebenarnya "[^\d\w]" sama dengan "[^\w]", yaitu
sama dengan "[\W]". Pikirkan hukum DeMorgan.

Sebenarnya, singkatan titik dan "\d\s\w\D\S\W" itu sendiri merupakan jenis
kelas karakter, jadi yang dikelilingi oleh tanda kurung hanyalah satu jenis karakter
kelas. Ketika kita perlu membuat perbedaan, kita menyebutnya sebagai "karakter yang dikurung"
kelas."

Jangkar yang berguna dalam regexps dasar adalah kata jangkar "\B". Ini cocok dengan batas
antara karakter kata dan karakter non-kata "\w\W" atau "\W\w":

$x = "Housecat mengkategorikan rumah dan kucing";
$x =~ /cat/; # cocok dengan kucing di 'housecat'
$x =~ /\bcat/; # cocok dengan kucing di 'catenates'
$x =~ /cat\b/; # cocok dengan kucing di 'housecat'
$x =~ /\bcat\b/; # cocok dengan 'kucing' di akhir string

Perhatikan pada contoh terakhir, akhir string dianggap sebagai batas kata.

Untuk pemrosesan bahasa alami (sehingga, misalnya, apostrof dimasukkan dalam kata-kata),
gunakan sebagai gantinya "\b{wb}"

"jangan" =~ / .+? \b{wb} /x; # cocok dengan seluruh string

Anda mungkin bertanya-tanya mengapa '.' cocok dengan semuanya kecuali "\n" - mengapa tidak semua karakter? Alasannya
adalah sering kali seseorang mencocokkan baris dan ingin mengabaikan baris baru
karakter. Misalnya, sementara string "\n" mewakili satu baris, kami ingin
anggap saja kosong. Kemudian

"" =~ /^$/; # pertandingan
"\n" =~ /^$/; # cocok, $ jangkar sebelum "\n"

"" =~ /./; # tidak cocok; itu membutuhkan char
"" =~ /^.$/; # tidak cocok; itu membutuhkan char
"\n" =~ /^.$/; # tidak cocok; itu membutuhkan karakter selain "\n"
"a" =~ /^.$/; # pertandingan
"a\n" =~ /^.$/; # cocok, $ jangkar sebelum "\n"

Perilaku ini nyaman, karena kami biasanya ingin mengabaikan baris baru ketika kami menghitung dan
mencocokkan karakter dalam satu baris. Namun, terkadang kami ingin melacak baris baru. Kita
bahkan mungkin ingin "^" dan "$" berlabuh di awal dan akhir baris di dalam string,
bukan hanya awal dan akhir string. Perl memungkinkan kita untuk memilih antara
mengabaikan dan memperhatikan baris baru dengan menggunakan pengubah "//s" dan "//m". "//S"
dan "//m" adalah singkatan dari single line dan multi-line dan menentukan apakah sebuah string harus
diperlakukan sebagai satu string kontinu, atau sebagai satu set garis. Kedua pengubah mempengaruhi dua
aspek bagaimana regexp ditafsirkan: 1) bagaimana '.' kelas karakter didefinisikan, dan
2) di mana jangkar "^" dan "$" dapat cocok. Berikut adalah empat kemungkinan
kombinasi:

· tidak ada pengubah (//): Perilaku default. '.' cocok dengan karakter apa pun kecuali "\n". "^"
cocok hanya di awal string dan "$" hanya cocok di akhir atau sebelumnya
baris baru di akhir.

· s modifier (//s): Perlakukan string sebagai satu garis panjang. '.' cocok dengan karakter apa pun, bahkan
"\n". "^" hanya cocok di awal string dan "$" hanya cocok di akhir
atau sebelum baris baru di akhir.

· m modifier (//m): Perlakukan string sebagai kumpulan beberapa baris. '.' cocok dengan karakter apa pun
kecuali "\n". "^" dan "$" dapat dicocokkan di awal atau akhir Apa pun baris di dalam
String.

· pengubah s dan m (//sm): Perlakukan string sebagai satu garis panjang, tetapi deteksi banyak
garis. '.' cocok dengan karakter apa pun, bahkan "\n". "^" dan "$", namun, dapat dicocokkan
di awal atau akhir Apa pun garis di dalam string.

Berikut adalah contoh aksi "//s" dan "//m":

$x = "Dulu ada seorang gadis\nYang memprogram dalam Perl\n";

$x =~ /^Siapa/; # tidak cocok, "Siapa" tidak di awal string
$x =~ /^Siapa/s; # tidak cocok, "Siapa" tidak di awal string
$x =~ /^Siapa/m; # cocok, "Siapa" di awal baris kedua
$x =~ /^Siapa/sm; # cocok, "Siapa" di awal baris kedua

$x =~ /gadis.Siapa/; # tidak cocok, "." tidak cocok dengan "\n"
$x =~ /girl.Who/s; # cocok, "." cocok dengan "\n"
$x =~ /gadis.Siapa/m; # tidak cocok, "." tidak cocok dengan "\n"
$x =~ /gadis.Siapa/sm; # cocok, "." cocok dengan "\n"

Sebagian besar waktu, perilaku default adalah yang diinginkan, tetapi "//s" dan "//m" adalah
kadang-kadang sangat berguna. Jika "//m" digunakan, awal string masih bisa
dicocokkan dengan "\A" dan akhir string masih dapat dicocokkan dengan jangkar "\Z"
(cocok dengan akhir dan baris baru sebelumnya, seperti "$"), dan "\z" (hanya cocok dengan akhir):

$x =~ /^Siapa/m; # cocok, "Siapa" di awal baris kedua
$x =~ /\ASiapa/m; # tidak cocok, "Siapa" tidak ada di awal string

$x =~ /gadis$/m; # cocok, "gadis" di akhir baris pertama
$x =~ /cewek\Z/m; # tidak cocok, "gadis" tidak ada di akhir string

$x =~ /Perl\Z/m; # cocok, "Perl" ada di baris baru sebelum akhir
$x =~ /Perl\z/m; # tidak cocok, "Perl" tidak ada di akhir string

Kita sekarang tahu cara membuat pilihan di antara kelas karakter dalam regexp. Bagaimana dengan
pilihan di antara kata-kata atau string karakter? Pilihan seperti itu akan dijelaskan di bagian berikutnya.

Sesuai ini or bahwa
Terkadang kami ingin regexp kami dapat mencocokkan kemungkinan kata yang berbeda atau
string karakter. Hal ini dicapai dengan menggunakan alternasi metakarakter "|". Ke
cocokkan "anjing" atau "kucing", kami membentuk regexp "anjing|kucing". Seperti sebelumnya, Perl akan mencoba menandingi
regexp pada titik sedini mungkin dalam string. Di setiap posisi karakter, Perl
pertama-tama akan mencoba mencocokkan alternatif pertama, "anjing". Jika "anjing" tidak cocok, Perl akan
kemudian coba alternatif berikutnya, "kucing". Jika "kucing" tidak cocok, maka pertandingan gagal
dan Perl pindah ke posisi berikutnya dalam string. Beberapa contoh:

"kucing dan anjing" =~ /kucing|anjing|burung/; # cocok dengan "kucing"
"kucing dan anjing" =~ /anjing|kucing|burung/; # cocok dengan "kucing"

Meskipun "anjing" adalah alternatif pertama di regexp kedua, "kucing" dapat menandingi
sebelumnya dalam string.

"kucing" =~ /c|ca|kucing|kucing/; # cocok dengan "c"
"kucing" =~ /kucing|kucing|ca|c/; # cocok dengan "kucing"

Di sini, semua alternatif cocok pada posisi string pertama, jadi alternatif pertama adalah
yang cocok. Jika beberapa alternatif adalah pemotongan dari yang lain, masukkan
yang terpanjang terlebih dahulu untuk memberi mereka kesempatan untuk mencocokkan.

"cab" =~ /a|b|c/ # cocok dengan "c"
# /a|b|c/ == /[abc]/

Contoh terakhir menunjukkan bahwa kelas karakter seperti pergantian karakter.
Pada posisi karakter tertentu, alternatif pertama yang memungkinkan regexp cocok untuk
berhasil akan menjadi salah satu yang cocok.

Pengelompokan hal dan hirarkis sesuai
Pergantian memungkinkan regexp untuk memilih di antara alternatif, tetapi dengan sendirinya itu
tidak memuaskan. Alasannya adalah bahwa setiap alternatif adalah seluruh regexp, tetapi kadang-kadang kita ingin
alternatif hanya untuk bagian dari regexp. Misalnya, kita ingin mencari
housecats atau pembantu rumah tangga. Regexp "housecat|housekeeper" cocok dengan tagihannya, tetapi adalah
tidak efisien karena kami harus mengetik "rumah" dua kali. Akan menyenangkan untuk memiliki bagian dari
regexp menjadi konstan, seperti "rumah", dan beberapa bagian memiliki alternatif, seperti "kucing|penjaga".

pengelompokan metakarakter "()" memecahkan masalah ini. Pengelompokan memungkinkan bagian dari regexp untuk
diperlakukan sebagai satu kesatuan. Bagian dari regexp dikelompokkan dengan melampirkannya di
tanda kurung. Jadi kita bisa menyelesaikan "housecat|housekeeper" dengan membentuk regexp sebagai
"rumah(kucing|penjaga)". Regexp "rumah(kucing|penjaga)" berarti cocok dengan "rumah" diikuti oleh
baik "kucing" atau "penjaga". Beberapa contoh lagi adalah

/(a|b)b/; # cocok dengan 'ab' atau 'bb'
/(ac|b)b/; # cocok dengan 'acb' atau 'bb'
/(^a|b)c/; # cocok dengan 'ac' di awal string atau 'bc' di mana saja
/(a|[bc])d/; # cocok dengan 'iklan', 'bd', atau 'cd'

/rumah(kucing|)/; # cocok dengan 'housecat' atau 'house'
/rumah(kucing(s|)|)/; # cocok dengan 'housecats' atau 'housecat' atau
# 'rumah'. Grup catatan dapat disarangkan.

/(19|20|)\d\d/; # tahun kecocokan 19xx, 20xx, atau masalah Y2K, xx
"20" =~ /(19|20|)\d\d/; # cocok dengan alternatif nol '()\d\d',
# karena '20\d\d' tidak cocok

Pergantian berperilaku dengan cara yang sama dalam kelompok seperti di luarnya: pada posisi string tertentu,
alternatif paling kiri yang memungkinkan regexp untuk mencocokkan diambil. Jadi dalam contoh terakhir di
posisi string pertama, "20" cocok dengan alternatif kedua, tetapi tidak ada yang tersisa
untuk mencocokkan dua digit berikutnya "\d\d". Jadi Perl beralih ke alternatif berikutnya, yang
adalah alternatif nol dan itu berfungsi, karena "20" adalah dua digit.

Proses mencoba satu alternatif, melihat apakah itu cocok, dan beralih ke yang berikutnya
alternatif, sambil kembali ke string dari mana alternatif sebelumnya dicoba,
jika tidak, disebut mundur. Istilah 'mundur' berasal dari gagasan bahwa
mencocokkan regexp seperti berjalan-jalan di hutan. Berhasil mencocokkan regexp seperti
tiba di suatu tempat tujuan. Ada banyak kemungkinan trailhead, satu untuk setiap string
posisi, dan masing-masing dicoba secara berurutan, dari kiri ke kanan. Dari setiap trailhead mungkin ada
banyak jalan, beberapa di antaranya membawa Anda ke sana, dan beberapa jalan buntu. Saat kamu berjalan
sepanjang jalan setapak dan menemui jalan buntu, Anda harus mundur di sepanjang jalan setapak ke yang sebelumnya
titik untuk mencoba jejak lain. Jika Anda mencapai tujuan Anda, Anda segera berhenti dan lupa
tentang mencoba semua jalur lainnya. Anda gigih, dan hanya jika Anda telah mencoba semua
jejak dari semua trailheads dan tidak tiba di tujuan Anda, apakah Anda menyatakan
kegagalan. Untuk lebih jelasnya, berikut adalah analisis langkah demi langkah tentang apa yang dilakukan Perl ketika mencoba
untuk mencocokkan regexp

"abcde" =~ /(abd|abc)(df|d|de)/;

0 Mulai dengan huruf pertama dalam string 'a'.

1 Coba alternatif pertama di grup pertama 'abd'.

2 Cocokkan 'a' diikuti dengan 'b'. Sejauh ini baik.

3 'd' di regexp tidak cocok dengan 'c' di string - jalan buntu. Jadi mundur dua
karakter dan pilih alternatif kedua di grup pertama 'abc'.

4 Cocokkan 'a' diikuti dengan 'b' diikuti dengan 'c'. Kami sedang berguling dan telah memuaskan
kelompok pertama. Setel $1 ke 'abc'.

5 Pindah ke grup kedua dan pilih alternatif pertama 'df'.

6 Cocokkan 'd'.

7 'f' di regexp tidak cocok dengan 'e' di string, jadi jalan buntu. Mundur satu
karakter dan memilih alternatif kedua di kelompok kedua 'd'.

8 'd' cocok. Pengelompokan kedua terpenuhi, jadi atur $2 ke 'd'.

9 Kami berada di akhir regexp, jadi kami selesai! Kami telah mencocokkan 'abcd' dari
string "abcde".

Ada beberapa hal yang perlu diperhatikan tentang analisis ini. Pertama, alternatif ketiga dalam
grup kedua 'de' juga mengizinkan pertandingan, tetapi kami berhenti sebelum kami mencapainya - pada saat tertentu
posisi karakter, paling kiri menang. Kedua, kami bisa mendapatkan kecocokan pada awalnya
posisi karakter string 'a'. Jika tidak ada pertandingan di posisi pertama,
Perl akan pindah ke posisi karakter kedua 'b' dan mencoba mencocokkan lagi.
Hanya ketika semua jalur yang mungkin di semua posisi karakter yang mungkin telah habis, barulah
Perl menyerah dan menyatakan "$string =~ /(abd|abc)(df|d|de)/;" menjadi palsu.

Bahkan dengan semua pekerjaan ini, pencocokan regexp terjadi sangat cepat. Untuk mempercepat,
Perl mengkompilasi regexp ke dalam urutan opcode yang kompak yang sering dapat ditampung di dalam a
cache prosesor. Ketika kode dieksekusi, opcode ini kemudian dapat berjalan dengan kecepatan penuh
dan mencari dengan sangat cepat.

Ekstraksi korek api
Metakarakter pengelompokan "()" juga melayani fungsi lain yang sama sekali berbeda: mereka
memungkinkan ekstraksi bagian dari string yang cocok. Ini sangat berguna untuk ditemukan
tahu apa yang cocok dan untuk pemrosesan teks secara umum. Untuk setiap pengelompokan, bagian yang
cocok di dalam masuk ke variabel khusus $1, $2, dll. Mereka dapat digunakan seperti
variabel biasa:

# ekstrak jam, menit, detik
if ($time =~ /(\d\d):(\d\d):(\d\d)/) { # cocok dengan format jj:mm:dd
$jam = $1;
$menit = $2;
$detik = $3;
}

Sekarang, kita tahu bahwa dalam konteks skalar, "$time =~ /(\d\d):(\d\d):(\d\d)/" mengembalikan nilai true atau
nilai palsu. Namun, dalam konteks daftar, ini mengembalikan daftar nilai yang cocok
"($1,$2,$3)". Jadi kita bisa menulis kode lebih kompak sebagai

# ekstrak jam, menit, detik
($jam, $menit, $detik) = ($waktu =~ /(\d\d):(\d\d):(\d\d)/);

Jika pengelompokan dalam regexp bersarang, $1 mendapatkan grup dengan pembukaan paling kiri
kurung, $2 kurung buka berikutnya, dll. Berikut adalah regexp dengan grup bersarang:

/(ab(cd|ef)((gi)|j))/;
1 2 34

Jika regexp ini cocok, $1 berisi string yang dimulai dengan 'ab', $2 disetel ke 'cd'
atau 'ef', $3 sama dengan 'gi' atau 'j', dan $4 disetel ke 'gi', seperti $3, atau
tetap tidak terdefinisi.

Untuk kenyamanan, Perl menetapkan $+ ke string yang dipegang oleh angka tertinggi $1, $2,... that
ditugaskan (dan, agak terkait, $^N dengan nilai $1, $2,... terbaru
ditugaskan; yaitu $1, $2,... terkait dengan kurung tutup paling kanan yang digunakan dalam
pertandingan).

Referensi balik
Terkait erat dengan variabel yang cocok $1, $2, ... adalah referensi balik "\g1",
"\g2",... Backreferences hanyalah variabel yang cocok yang dapat digunakan dalam sebuah reg.
Ini adalah fitur yang sangat bagus; apa yang cocok nanti di regexp dibuat bergantung pada apa
cocok sebelumnya di regexp. Misalkan kita ingin mencari kata ganda dalam sebuah teks,
seperti 'the'. Regexp berikut menemukan semua 3 huruf ganda dengan spasi di antaranya:

/\b(\w\w\w)\s\g1\b/;

Pengelompokan memberikan nilai ke \g1, sehingga urutan 3 huruf yang sama digunakan untuk keduanya
bagian.

Tugas serupa adalah menemukan kata-kata yang terdiri dari dua bagian yang identik:

% simple_grep '^(\w\w\w\w|\w\w\w|\w\w|\w)\g1$' /usr/dict/words
beri-beri
boo
kelapa
mama
berbisik
ayah

Regexp memiliki pengelompokan tunggal yang mempertimbangkan kombinasi 4 huruf, lalu 3 huruf
kombinasi, dll., dan menggunakan "\g1" untuk mencari pengulangan. Meskipun $1 dan "\g1" mewakili
hal yang sama, perawatan harus dilakukan untuk menggunakan variabel yang cocok $1, $2,... only di luar a
regexp dan referensi balik "\g1", "\g2",... hanya dalam sebuah regexp; tidak melakukannya dapat menyebabkan
hasil yang mengejutkan dan tidak memuaskan.

Relatif referensi balik
Menghitung kurung buka untuk mendapatkan nomor yang benar untuk referensi balik adalah kesalahan-
rawan segera setelah ada lebih dari satu kelompok penangkap. Teknik yang lebih nyaman
menjadi tersedia dengan Perl 5.10: referensi balik relatif. Untuk merujuk segera
grup tangkapan sebelumnya satu sekarang dapat menulis "\g{-1}", yang berikutnya tetapi terakhir tersedia melalui
"\g{-2}", dan seterusnya.

Alasan bagus lainnya selain keterbacaan dan pemeliharaan untuk menggunakan relatif
referensi balik diilustrasikan oleh contoh berikut, di mana pola sederhana untuk
pencocokan string aneh digunakan:

$a99a = '([az])(\d)\g2\g1'; # cocok dengan a11a, g22g, x33x, dll.

Sekarang setelah pola ini disimpan sebagai string praktis, kita mungkin merasa tergoda untuk menggunakannya sebagai
bagian dari beberapa pola lain:

$baris = "kode=e99e";
if ($line =~ /^(\w+)=$a99a$/){ # perilaku tak terduga!
print "$1 valid\n";
} Else {
print "baris buruk: '$baris'\n";
}

Tapi ini tidak cocok, setidaknya tidak seperti yang diharapkan. Hanya setelah memasukkan
diinterpolasi $a99a dan melihat teks lengkap yang dihasilkan dari regexp apakah jelas bahwa
backreferences telah menjadi bumerang. Subekspresi "(\w+)" telah mengambil nomor 1 dan
menurunkan grup di $a99a dengan satu peringkat. Ini dapat dihindari dengan menggunakan relative
referensi balik:

$a99a = '([az])(\d)\g{-1}\g{-2}'; #aman untuk diinterpolasi

Bernama referensi balik
Perl 5.10 juga memperkenalkan grup penangkap bernama dan referensi belakang bernama. Untuk melampirkan nama
ke grup penangkap, Anda menulis "(? ...)" atau "(?'nama'...)".
backreference kemudian dapat ditulis sebagai "\g{name}". Diperbolehkan untuk melampirkan yang sama
nama ke lebih dari satu grup, tetapi hanya yang paling kiri dari kumpulan eponymous yang dapat
dirujuk. Di luar pola, grup penangkap bernama dapat diakses melalui "%+"
hash.

Dengan asumsi bahwa kita harus mencocokkan tanggal kalender yang mungkin diberikan di salah satu dari ketiganya
format yyyy-mm-dd, mm/dd/yyyy atau dd.mm.yyyy, kita dapat menulis tiga pola yang sesuai di mana
kami menggunakan 'd', 'm' dan 'y' masing-masing sebagai nama grup yang menangkap yang bersangkutan
komponen tanggal. Operasi pencocokan menggabungkan tiga pola sebagai alternatif:

$fmt1 = '(? \d\d\d\d)-(? \DD)-(? \DD)';
$fmt2 = '(? \DD)/(? \DD)/(? \d\d\d\d)';
$fmt3 = '(? \DD)\.(? \DD)\.(? \d\d\d\d)';
untuk saya $d qw( 2006-10-21 15.01.2007 10/31/2005 ){
jika ( $d =~ m{$fmt1|$fmt2|$fmt3} ){
print "hari=$+{h} bulan=$+{m} tahun=$+{y}\n";
}
}

Jika salah satu alternatif cocok, hash "%+" pasti berisi tiga nilai kunci
pasang.

Alternatif menangkap kelompok penomoran
Namun teknik penomoran grup penangkap lainnya (juga dari Perl 5.10) berhubungan dengan
masalah mengacu pada kelompok dalam satu set alternatif. Pertimbangkan pola untuk
mencocokkan waktu dalam sehari, gaya sipil atau militer:

if ( $waktu =~ /(\d\d|\d):(\d\d)|(\d\d)(\d\d)/ ){
# proses jam dan menit
}

Pemrosesan hasil memerlukan pernyataan if tambahan untuk menentukan apakah $1 dan $2
atau $3 dan $4 berisi barang. Akan lebih mudah jika kita bisa menggunakan nomor grup 1 dan 2
di alternatif kedua juga, dan inilah tepatnya konstruksi yang dikurung
"(?|...)", mengatur pencapaian alternatif. Ini adalah versi lanjutan dari sebelumnya
pola:

if($waktu =~ /(?|(\d\d|\d):(\d\d)|(\d\d)(\d\d))\s+([AZ][AZ][ AZ])/){
print "jam=$1 menit=$2 zona=$3\n";
}

Dalam grup penomoran alternatif, nomor grup dimulai pada posisi yang sama untuk masing-masing
alternatif. Setelah grup, penomoran berlanjut dengan satu lebih tinggi dari maksimum yang dicapai
di semua alternatif.

Posisi informasi
Selain apa yang dicocokkan, Perl juga menyediakan posisi apa yang dicocokkan sebagai
isi larik "@-" dan "@+". "$-[0]" adalah posisi awal dari keseluruhan
cocok dan $+[0] adalah posisi akhir. Demikian pula, "$-[n]" adalah posisi dari
awal pertandingan $n dan $+[n] adalah posisi akhir. Jika $n tidak terdefinisi, begitu juga
"$-[n]" dan $+[n]. Lalu kode ini

$x = "Mmm...donat, pikir Homer";
$x =~ /^(Mmm|Yech)\.\.\.(donat|kacang polong)/; # pertandingan
foreach $exp (1..$#-) {
print "Cocokkan $exp: '${$exp}' pada posisi ($-[$exp],$+[$exp])\n";
}

cetakan

Pertandingan 1: 'Mmm' di posisi (0,3)
Cocokkan 2: 'donat' di posisi (6,11)

Bahkan jika tidak ada pengelompokan dalam regexp, masih mungkin untuk mengetahui apa sebenarnya
cocok dalam sebuah string. Jika Anda menggunakannya, Perl akan menyetel "$`" ke bagian string sebelumnya
pertandingan, akan mengatur $& ke bagian string yang cocok, dan akan mengatur "$'" ke
bagian dari string setelah pertandingan. Sebuah contoh:

$x = "kucing menangkap tikus";
$x =~ /cat/; # $` = 'the ', $& = 'cat', $' = ' menangkap tikus'
$x =~ /the/; # $` = '', $& = 'the', $' = ' kucing menangkap tikus'

Di pertandingan kedua, "$`" sama dengan '' karena regexp cocok dengan karakter pertama
posisi di string dan berhenti; tidak pernah melihat 'the' kedua.

Jika kode Anda dijalankan pada versi Perl lebih awal dari 5.20, perlu diperhatikan bahwa
menggunakan "$`" dan "$'" sedikit memperlambat pencocokan regexp, sementara $& memperlambatnya menjadi
tingkat lebih rendah, karena jika mereka digunakan dalam satu regexp dalam suatu program, mereka dihasilkan untuk
semua regexps dalam program. Jadi, jika kinerja mentah adalah tujuan aplikasi Anda, mereka
harus dihindari. Jika Anda perlu mengekstrak substring yang sesuai, gunakan "@-" dan "@+"
sebagai gantinya:

$` sama dengan substr( $x, 0, $-[0] )
$& sama dengan substr( $x, $-[0], $+[0]-$-[0] )
$' sama dengan substr( $x, $+[0] )

Pada Perl 5.10, variabel "${^PREMATCH}", "${^MATCH}" dan "${^POSTMATCH}" mungkin
digunakan. Ini hanya diatur jika pengubah "/ p" ada. Akibatnya mereka tidak
menghukum sisa program. Di Perl 5.20, "${^PREMATCH}", "${^MATCH}" dan
"${^POSTMATCH}" tersedia baik "/p" telah digunakan atau belum (pengubahnya adalah
diabaikan), dan "$`", "$'" dan $& tidak menyebabkan perbedaan kecepatan.

Tidak menangkap pengelompokan
Sebuah kelompok yang diperlukan untuk menggabungkan satu set alternatif mungkin atau mungkin tidak berguna sebagai
kelompok penangkapan. Jika tidak, itu hanya membuat tambahan yang berlebihan untuk himpunan
nilai grup tangkap yang tersedia, di dalam maupun di luar regexp. Tidak menangkap
pengelompokan, dilambangkan dengan "(?:regexp)", masih memungkinkan regexp diperlakukan sebagai satu unit,
tetapi jangan membuat grup penangkap pada saat yang bersamaan. Baik menangkap dan tidak menangkap
pengelompokan diizinkan untuk hidup berdampingan dalam regexp yang sama. Karena tidak ada ekstraksi,
pengelompokan non-menangkap lebih cepat daripada menangkap pengelompokan. Pengelompokan yang tidak menangkap adalah
juga berguna untuk memilih dengan tepat bagian regexp mana yang akan diekstraksi untuk dicocokkan
variabel:

# cocok dengan angka, $1-$4 ditetapkan, tetapi kami hanya menginginkan $1
/([+-]?\ *(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?)/;

# mencocokkan nomor lebih cepat, hanya $1 yang ditetapkan
/([+-]?\ *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?)/;

# cocokkan angka, dapatkan $1 = bilangan bulat, $2 = eksponen
/([+-]?\ *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE]([+-]?\d+))?)/;

Pengelompokan yang tidak menangkap juga berguna untuk menghilangkan elemen pengganggu yang dikumpulkan dari a
operasi split di mana tanda kurung diperlukan karena beberapa alasan:

$x = '12aba34ba5';
@num = split /(a|b)+/, $x; # @bil = ('12','a','34','a','5')
@num = split /(?:a|b)+/, $x; # @angka = ('12','34','5')

Di Perl 5.22 dan yang lebih baru, semua grup dalam regexp dapat diatur ke non-capturing dengan menggunakan
bendera "/ n" baru:

"halo" =~ /(hai|halo)/n; # $1 tidak disetel!

Lihat "n" di perlre untuk informasi lebih lanjut.

Sesuai pengulangan
Contoh-contoh di bagian sebelumnya menunjukkan kelemahan yang mengganggu. Kami hanya cocok
Kata 3 huruf, atau potongan kata yang terdiri dari 4 huruf atau kurang. Kami ingin bisa mencocokkan
kata-kata atau, lebih umum, string dengan panjang berapa pun, tanpa menuliskan alternatif yang membosankan
seperti "\w\w\w\w|\w\w\w|\w\w|\w".

Inilah masalahnya pembilang metakarakter "?", "*", "+", dan "{}" adalah
dibuat untuk. Mereka memungkinkan kita untuk membatasi jumlah pengulangan untuk sebagian dari regexp yang kita
anggap sebagai pertandingan. Kuantifier diletakkan tepat setelah karakter, karakter
kelas, atau pengelompokan yang ingin kita tentukan. Mereka memiliki arti sebagai berikut:

· "A?" artinya: cocokkan 'a' 1 atau 0 kali

· "a*" berarti: cocokkan 'a' 0 kali atau lebih, yaitu berapa kali

· "a+" berarti: mencocokkan 'a' 1 kali atau lebih, yaitu, setidaknya sekali

· "a{n,m}" berarti: cocok dengan setidaknya "n" kali, tetapi tidak lebih dari "m" kali.

· "a{n,}" artinya: cocokkan setidaknya "n" atau lebih

· "a{n}" artinya: sama persis dengan "n" kali

Berikut adalah beberapa contoh:

/[az]+\s+\d*/; # cocok dengan kata kecil, setidaknya satu spasi, dan
# sejumlah digit
/(\w+)\s+\g1/; # cocokkan kata-kata ganda dengan panjang sewenang-wenang
/ya saya; # cocok dengan 'y', 'Y', atau 'ya' yang tidak peka huruf besar-kecil
$tahun =~ /^\d{2,4}$/; # pastikan tahun minimal 2 tetapi tidak lebih
# dari 4 digit
$tahun =~ /^\d{4}$|^\d{2}$/; # pertandingan yang lebih baik; buang tanggal 3 digit
$tahun =~ /^\d{2}(\d{2})?$/; # hal yang sama ditulis berbeda.
# Namun, ini menangkap dua yang terakhir
# digit dalam $1 dan yang lainnya tidak.

% simple_grep '^(\w+)\g1$' /usr/dict/words # bukankah ini lebih mudah?
beri-beri
boo
kelapa
mama
berbisik
ayah

Untuk semua quantifier ini, Perl akan mencoba mencocokkan string sebanyak mungkin,
sambil tetap membiarkan regexp berhasil. Jadi dengan "/a?.../", Perl pertama-tama akan mencoba untuk
cocokkan regexp dengan hadiah "a"; jika gagal, Perl akan mencoba mencocokkan regexp
tanpa hadiah "a". Untuk quantifier "*", kami mendapatkan yang berikut:

$x = "kucing bertopi";
$x =~ /^(.*)(cat)(.*)$/; # pertandingan,
# $1 = 'yang'
# $2 = 'kucing'
# $3 = 'di topi'

Itulah yang mungkin kita harapkan, korek api menemukan satu-satunya "kucing" di tali dan menguncinya
dia. Pertimbangkan, bagaimanapun, regexp ini:

$x =~ /^(.*)(at)(.*)$/; # pertandingan,
# $1 = 'kucing di h'
# $2 = 'di'
# $3 = '' (0 karakter cocok)

Orang mungkin awalnya menebak bahwa Perl akan menemukan "at" di "cat" dan berhenti di situ, tapi itu
tidak akan memberikan string terpanjang yang mungkin ke quantifier pertama ".*". Sebagai gantinya,
kuantifier pertama ".*" mengambil string sebanyak mungkin sambil tetap memiliki
pertandingan regexp. Dalam contoh ini, itu berarti memiliki urutan "at" dengan "at" terakhir di
tali. Prinsip penting lainnya yang diilustrasikan di sini adalah bahwa, ketika ada dua atau
lebih banyak elemen dalam regexp, the paling kiri quantifier, jika ada, dapatkan sebanyak mungkin
string mungkin, meninggalkan sisa regexp untuk memperebutkan memo. Jadi di
contoh kita, quantifier pertama ".*" mengambil sebagian besar string, sedangkan yang kedua
quantifier ".*" mendapatkan string kosong. Quantifier yang mengambil sebanyak mungkin string
mungkin disebut maksimum pertandingan or serakah quantifier.

Ketika regexp dapat mencocokkan string dengan beberapa cara berbeda, kita dapat menggunakan prinsip-prinsip
di atas untuk memprediksi ke arah mana regexp akan cocok:

· Prinsip 0: Secara keseluruhan, regexp apa pun akan dicocokkan sedini mungkin
posisi dalam tali.

· Prinsip 1: Dalam sebuah pergantian "a|b|c...", alternatif paling kiri yang memungkinkan a
pertandingan untuk seluruh regexp akan menjadi yang digunakan.

· Prinsip 2: Kuantifier pencocokan maksimal "?", "*", "+" dan "{n,m}" akan masuk
kecocokan umum sebanyak mungkin string sambil tetap mengizinkan seluruh regexp
untuk mencocokkan.

· Prinsip 3: Jika ada dua atau lebih elemen dalam regexp, paling kiri serakah
quantifier, jika ada, akan mencocokkan sebanyak mungkin string sambil tetap mengizinkan
seluruh regexp untuk dicocokkan. Penghitung serakah paling kiri berikutnya, jika ada, akan mencoba
mencocokkan sebanyak mungkin string yang tersisa untuknya, selagi masih
memungkinkan seluruh regexp untuk mencocokkan. Dan seterusnya, sampai semua elemen regexp adalah
puas.

Seperti yang telah kita lihat di atas, Prinsip 0 mengesampingkan yang lain. Regexp akan dicocokkan sebagai
sedini mungkin, dengan prinsip-prinsip lain yang menentukan bagaimana regexp cocok pada saat itu
posisi karakter paling awal.

Berikut adalah contoh dari prinsip-prinsip ini dalam tindakan:

$x = "Republik pemrograman Perl";
$x =~ /^(.+)(e|r)(.*)$/; # pertandingan,
# $1 = 'Republik pemrograman Pe'
# $2 = 'r'
# $3 = 'l'

Regexp ini cocok dengan posisi string paling awal, 'T'. Orang mungkin berpikir bahwa "e", menjadi
paling kiri dalam pergantian, akan dicocokkan, tetapi "r" menghasilkan string terpanjang di
kuantor pertama.

$x =~ /(m{1,2})(.*)$/; # pertandingan,
# $1 = 'mm'
# $2 = 'meninggalkan republik Perl'

Di sini, Kecocokan paling awal adalah pada 'm' pertama dalam "pemrograman". "m{1,2}" adalah
kuantifier pertama, sehingga cocok dengan "mm" maksimal.

$x =~ /.*(m{1,2})(.*)$/; # pertandingan,
# $1 = 'm'
# $2 = 'meninggalkan republik Perl'

Di sini, regexp cocok di awal string. Kuantifier pertama ".*" meraih sebagai
sebanyak mungkin, hanya menyisakan satu 'm' untuk pengukur kedua "m{1,2}".

$x =~ /(.?)(m{1,2})(.*)$/; # pertandingan,
# $1 = 'a'
# $2 = 'mm'
# $3 = 'meninggalkan republik Perl'

Di Sini, ".?" memakan satu karakter maksimalnya pada posisi sedini mungkin dalam string,
'a' dalam "pemrograman", meninggalkan "m{1,2}" kesempatan untuk mencocokkan kedua "m". Akhirnya,

"aXXXb" =~ /(X*)/; # cocok dengan $1 = ''

karena dapat mencocokkan nol salinan 'X' di awal string. Jika Anda pasti
ingin mencocokkan setidaknya satu 'X', gunakan "X+", bukan "X*".

Terkadang keserakahan itu tidak baik. Kadang-kadang, kami ingin quantifiers untuk mencocokkan a minimal bagian
string, bukan sepotong maksimal. Untuk tujuan ini, Larry Wall menciptakan minimal
pertandingan or tidak serakah quantifier "??", "*?", "+?", dan "{}?". Ini adalah yang biasa
quantifier dengan "?" ditambahkan kepada mereka. Mereka memiliki arti sebagai berikut:

· "A??" artinya: cocokkan 'a' 0 atau 1 kali. Coba 0 dulu, lalu 1.

· "A*?" berarti: cocokkan 'a' 0 kali atau lebih, yaitu, berapa kali pun, tetapi sesedikit
mungkin

· "a+?" berarti: cocokkan 'a' 1 kali atau lebih, yaitu, setidaknya sekali, tetapi sesedikit mungkin
mungkin

· "a{n,m}?" berarti: cocok setidaknya "n" kali, tidak lebih dari "m" kali, sesedikit
mungkin

· "NS,}?" artinya: cocokkan setidaknya "n" kali, tetapi sesedikit mungkin

· "NS}?" berarti: sama persis dengan "n" kali. Karena kita sama persis dengan "n" kali, "a{n}?"
setara dengan "a{n}" dan hanya ada untuk konsistensi notasi.

Mari kita lihat contoh di atas, tetapi dengan quantifier minimal:

$x = "Republik pemrograman Perl";
$x =~ /^(.+?)(e|r)(.*)$/; # pertandingan,
# $1 = 'Th'
# $2 = 'e'
# $3 = ' memprogram republik Perl'

String minimal yang memungkinkan awal string "^" dan pergantian ke
cocok adalah "Th", dengan alternatif "e|r" cocok dengan "e". Kuantifier kedua ".*" adalah
bebas untuk melahap sisa tali.

$x =~ /(m{1,2}?)(.*?)$/; # pertandingan,
# $1 = 'm'
# $2 = 'ming republik Perl'

Posisi string pertama yang dapat dicocokkan oleh regexp ini adalah pada 'm' pertama dalam "pemrograman".
Pada posisi ini, minimal "m{1,2}?" cocok hanya satu 'm'. Meskipun yang kedua
penghitung ".*?" lebih suka tidak mencocokkan karakter, itu dibatasi oleh akhir
jangkar string "$" untuk mencocokkan sisa string.

$x =~ /(.*?)(m{1,2}?)(.*)$/; # pertandingan,
# $1 = 'Program'
# $2 = 'm'
# $3 = 'ming republik Perl'

Dalam regexp ini, Anda mungkin mengharapkan quantifier minimal pertama ".*?" untuk mencocokkan yang kosong
string, karena tidak dibatasi oleh jangkar "^" untuk mencocokkan awal kata.
Prinsip 0 berlaku di sini, namun. Karena mungkin saja seluruh regexp cocok
di awal string, itu akan cocok di awal string. Jadi yang pertama
quantifier harus mencocokkan semuanya hingga "m" pertama. Kuantifier minimal kedua
cocok hanya satu "m" dan kuantifier ketiga cocok dengan sisa string.

$x =~ /(.??)(m{1,2})(.*)$/; # pertandingan,
# $1 = 'a'
# $2 = 'mm'
# $3 = 'meninggalkan republik Perl'

Sama seperti pada regexp sebelumnya, quantifier pertama ".???" bisa cocok paling awal di posisi
'a', begitulah. Kuantifier kedua serakah, jadi cocok dengan "mm", dan yang ketiga
cocok dengan sisa string.

Kita dapat memodifikasi prinsip 3 di atas untuk memperhitungkan quantifier non-serakah:

· Prinsip 3: Jika ada dua atau lebih elemen dalam sebuah regexp, yang paling kiri serakah (non-
serakah) quantifier, jika ada, akan mencocokkan sebanyak (sedikit) string mungkin
sementara masih memungkinkan seluruh regexp untuk mencocokkan. Selanjutnya paling kiri serakah (non-greedy)
quantifier, jika ada, akan mencoba mencocokkan sebanyak (sedikit) string yang tersisa
tersedia untuk itu mungkin, sambil tetap memungkinkan seluruh regexp untuk dicocokkan. Sehingga
aktif, sampai semua elemen regexp terpenuhi.

Sama seperti pergantian, quantifiers juga rentan terhadap backtracking. Berikut adalah langkah-
analisis langkah demi langkah dari contoh

$x = "kucing bertopi";
$x =~ /^(.*)(at)(.*)$/; # pertandingan,
# $1 = 'kucing di h'
# $2 = 'di'
# $3 = '' (0 cocok)

0 Mulai dengan huruf pertama dalam string 't'.

1 Penghitung pertama '.*' dimulai dengan mencocokkan seluruh string 'kucing di
topi'.

2 'a' di elemen regexp 'at' tidak cocok dengan akhir string. Mundur satu
karakter.

3 'a' dalam elemen regexp 'at' masih tidak cocok dengan huruf terakhir dari string 't',
jadi mundur satu karakter lagi.

4 Sekarang kita bisa mencocokkan 'a' dan 't'.

5 Pindah ke elemen ketiga '.*'. Karena kita berada di akhir string dan '.*' can
cocokkan 0 kali, tetapkan string kosong.

6 Kita selesai!

Sebagian besar waktu, semua pergerakan maju dan mundur ini terjadi dengan cepat dan pencarian
cepat. Namun, ada beberapa regexp patologis, yang waktu eksekusinya secara eksponensial
tumbuh dengan ukuran string. Struktur khas yang meledak di wajahmu adalah
formulir

/(a|b+)*/;

Masalahnya adalah quantifier tak tentu bersarang. Ada banyak cara berbeda untuk
mempartisi string dengan panjang n antara "+" dan "*": satu pengulangan dengan "b+" dari
panjang n, dua kali pengulangan dengan panjang "b+" pertama k dan yang kedua dengan panjang nk, m
pengulangan yang bitnya bertambah hingga panjang n, dll. Sebenarnya ada bilangan eksponensial
cara untuk mempartisi string sebagai fungsi dari panjangnya. Sebuah regexp mungkin beruntung dan
cocok di awal proses, tetapi jika tidak ada yang cocok, Perl akan mencoba setiap kemungkinan
sebelum menyerah. Jadi berhati-hatilah dengan "*", "{n,m}", dan "+" bersarang. Buku
Menguasai Reguler Ekspresi oleh Jeffrey Friedl memberikan diskusi yang luar biasa tentang ini dan
masalah efisiensi lainnya.

Posesif pengukur
Mundur selama pencarian tanpa henti untuk kecocokan mungkin membuang-buang waktu, terutama
ketika pertandingan pasti akan gagal. Perhatikan pola sederhana

/^\w+\s+\w+$/; # sebuah kata, spasi, sebuah kata

Kapan pun ini diterapkan pada string yang tidak cukup memenuhi harapan pola
seperti "abc" atau "abc def", mesin regex akan mundur, kira-kira sekali untuk
setiap karakter dalam string. Tapi kita tahu bahwa tidak ada jalan lain selain mengambil semua dari
karakter kata awal untuk mencocokkan pengulangan pertama, itu semua ruang harus dimakan oleh
bagian tengah, dan hal yang sama berlaku untuk kata kedua.

Dengan diperkenalkannya posesif pengukur di Perl 5.10, kami memiliki cara untuk
menginstruksikan mesin regex untuk tidak mundur, dengan pengukur biasa dengan "+"
ditambahkan kepada mereka. Ini membuat mereka serakah dan juga pelit; begitu mereka berhasil, mereka tidak akan melakukannya
memberikan apa pun kembali untuk mengizinkan solusi lain. Mereka memiliki arti sebagai berikut:

· "a{n,m}+" berarti: cocokkan setidaknya "n" kali, tidak lebih dari "m" kali, sebanyak
mungkin, dan jangan menyerah. "a?+" adalah kependekan dari "a{0,1}+"

· "a{n,}+" artinya: cocokkan setidaknya "n" kali, tetapi sebanyak mungkin, dan jangan
menyerah apapun. "a*+" adalah kependekan dari "a{0,}+" dan "a++" adalah kependekan dari "a{1,}+".

· "a{n}+" berarti: sama persis dengan "n" kali. Itu hanya ada untuk konsistensi notasi.

Kuantifier posesif ini mewakili kasus khusus dari konsep yang lebih umum,
independen subekspresi, Lihat di bawah.

Sebagai contoh di mana kuantifier posesif cocok, kami mempertimbangkan untuk mencocokkan kutipan
string, seperti yang muncul dalam beberapa bahasa pemrograman. Garis miring terbalik digunakan sebagai
karakter pelarian yang menunjukkan bahwa karakter berikutnya harus dipahami secara harfiah, sebagai
karakter lain untuk string. Oleh karena itu, setelah kutipan pembukaan, kami mengharapkan
(mungkin kosong) urutan alternatif: beberapa karakter kecuali kutipan yang tidak lolos
atau garis miring terbalik atau karakter yang lolos.

/"(?:[^"\\]++|\\.)*+"/;

Bangunan a regexp
Pada titik ini, kita telah membahas semua konsep dasar regexp, jadi mari kita bahas lebih lanjut
melibatkan contoh ekspresi reguler. Kami akan membangun regexp yang cocok dengan angka.

Tugas pertama dalam membangun regexp adalah memutuskan apa yang ingin kita cocokkan dan apa yang kita inginkan
mengecualikan. Dalam kasus kami, kami ingin mencocokkan bilangan bulat dan bilangan floating point dan kami
ingin menolak string apa pun yang bukan angka.

Tugas selanjutnya adalah memecah masalah menjadi masalah yang lebih kecil yang mudah dikonversi
menjadi regexp.

Kasus paling sederhana adalah bilangan bulat. Ini terdiri dari urutan digit, dengan opsional
tanda di depan. Digit yang dapat kita wakili dengan "\d+" dan tandanya dapat dicocokkan dengan
"[+-]". Jadi regexp bilangan bulat adalah

/[+-]?\d+/; # cocok dengan bilangan bulat

Angka floating point berpotensi memiliki tanda, bagian integral, titik desimal, a
bagian pecahan, dan eksponen. Satu atau beberapa bagian ini opsional, jadi kita perlu
memeriksa kemungkinan yang berbeda. Angka floating point yang dalam bentuk yang tepat
termasuk 123., 0.345, .34, -1e6, dan 25.4E-72. Seperti halnya bilangan bulat, tanda di depan adalah
sepenuhnya opsional dan dapat dicocokkan dengan "[+-]?". Kita bisa melihatnya jika tidak ada
eksponen, bilangan floating point harus memiliki titik desimal, jika tidak bilangan bulat.
Kita mungkin tergoda untuk memodelkan ini dengan "\d*\.\d*", tetapi ini juga akan cocok dengan
titik desimal tunggal, yang bukan angka. Jadi tiga kasus bilangan floating point
tanpa eksponen adalah

/[+-]?\d+\./; #1., 321., dst.
/[+-]?\.\d+/; # .1, .234, dll.
/[+-]?\d+\.\d+/; #1.0, 30.56, dll.

Ini dapat digabungkan menjadi satu regexp dengan pergantian tiga arah:

/[+-]?(\d+\.\d+|\d+\.|\.\d+)/; # titik mengambang, tanpa eksponen

Dalam pergantian ini, penting untuk menempatkan '\d+\.\d+' sebelum '\d+\.'. Jika '\d+\.' NS
pertama, regexp akan dengan senang hati mencocokkannya dan mengabaikan bagian pecahan dari nomor tersebut.

Sekarang pertimbangkan angka floating point dengan eksponen. Pengamatan utama di sini adalah bahwa kedua
bilangan bulat dan angka dengan titik desimal diperbolehkan di depan eksponen. Kemudian
eksponen, seperti tanda keseluruhan, tidak tergantung pada apakah kita mencocokkan angka dengan
atau tanpa titik desimal, dan dapat 'dipisahkan' dari mantissa. Bentuk keseluruhan dari
regexp sekarang menjadi jelas:

/^(tanda opsional)(bilangan bulat | fp mantissa)(eksponen opsional)$/;

Eksponennya adalah "e" atau "E", diikuti oleh bilangan bulat. Jadi regexp eksponennya adalah

/[eE][+-]?\d+/; # eksponen

Menempatkan semua bagian bersama-sama, kami mendapatkan regexp yang cocok dengan angka:

/^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?$/; # Tdk!

Regexps panjang seperti ini mungkin mengesankan teman-teman Anda, tetapi bisa sulit untuk diuraikan. Di kompleks
situasi seperti ini, pengubah "//x" untuk pertandingan sangat berharga. Hal ini memungkinkan seseorang untuk menempatkan
spasi dan komentar yang hampir sewenang-wenang menjadi regexp tanpa memengaruhi artinya.
Dengan menggunakannya, kami dapat menulis ulang regexp 'diperpanjang' kami dalam bentuk yang lebih menyenangkan

/^
[+-]? # pertama, cocokkan dengan tanda opsional
( # lalu cocokkan bilangan bulat atau mantisa fp:
\d+\.\d+ # mantissa dari bentuk ab
|\d+\. # mantissa dari bentuk a.
|\.\d+ # mantissa dari bentuk .b
|\d+ # bilangan bulat berbentuk a
)
([eE][+-]?\d+)? # akhirnya, cocokkan eksponen secara opsional
$/x;

Jika spasi putih sebagian besar tidak relevan, bagaimana cara memasukkan karakter spasi dalam ekstensi
regexp? Jawabannya adalah dengan backslash '\ ' atau memasukkannya ke dalam kelas karakter "[ ]". Sama
berlaku untuk tanda pound: gunakan "\#" atau "[#]". Misalnya, Perl memungkinkan spasi antara
tanda dan mantissa atau bilangan bulat, dan kami dapat menambahkan ini ke regexp kami sebagai berikut:

/^
[+-]?\ * # pertama, cocokkan dengan tanda opsional *dan spasi*
( # lalu cocokkan bilangan bulat atau mantisa fp:
\d+\.\d+ # mantissa dari bentuk ab
|\d+\. # mantissa dari bentuk a.
|\.\d+ # mantissa dari bentuk .b
|\d+ # bilangan bulat berbentuk a
)
([eE][+-]?\d+)? # akhirnya, cocokkan eksponen secara opsional
$/x;

Dalam bentuk ini, lebih mudah untuk melihat cara menyederhanakan pergantian. Alternatif 1, 2,
dan 4 semuanya dimulai dengan "\d+", sehingga bisa diperhitungkan:

/^
[+-]?\ * # pertama, cocokkan dengan tanda opsional
( # lalu cocokkan bilangan bulat atau mantisa fp:
\d+ # mulai dengan ...
(
\.\d* # mantissa dari bentuk ab atau a.
)? # ? menangani bilangan bulat dari bentuk a
|\.\d+ # mantissa dari bentuk .b
)
([eE][+-]?\d+)? # akhirnya, cocokkan eksponen secara opsional
$/x;

atau ditulis dalam bentuk ringkas,

/^[+-]?\ *(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;

Ini adalah regexp terakhir kami. Untuk rekap, kami membuat regexp dengan

· menentukan tugas secara rinci,

· memecah masalah menjadi bagian-bagian yang lebih kecil,

· menerjemahkan bagian-bagian kecil menjadi regexps,

· menggabungkan regexps,

· dan mengoptimalkan regexp gabungan akhir.

Ini juga merupakan langkah-langkah khas yang terlibat dalam menulis program komputer. Ini membuat
masuk akal, karena ekspresi reguler pada dasarnya adalah program yang ditulis dalam sedikit
bahasa komputer yang menentukan pola.

Menggunakan reguler ekspresi in Perl
Topik terakhir dari Bagian 1 secara singkat mencakup bagaimana regexps digunakan dalam program Perl. Mana
mereka cocok dengan sintaks Perl?

Kami telah memperkenalkan operator yang cocok dalam default "/ regexp/" dan arbitrer
pembatas "m!regexp!" formulir. Kami telah menggunakan operator pengikatan "=~" dan negasinya "!~"
untuk menguji kecocokan string. Terkait dengan operator pencocokan, kami telah membahas
baris tunggal "//s", multi-baris "//m", case-insensitive "//i" dan pengubah diperpanjang "//x".
Ada beberapa hal lagi yang mungkin ingin Anda ketahui tentang operator yang cocok.

Melarang substitusi

Jika Anda mengubah $pattern setelah substitusi pertama terjadi, Perl akan mengabaikannya. Jika kamu
tidak ingin ada penggantian sama sekali, gunakan pembatas khusus "m''":

@pola = ('Seuss');
sementara (<>) {
cetak jika m'@pattern'; # cocok dengan '@pattern' literal, bukan 'Seuss'
}

Mirip dengan string, "m''" bertindak seperti apostrof pada regexp; semua pembatas "m" lainnya bertindak
seperti kutipan. Jika regexp mengevaluasi ke string kosong, regexp di terakhir
sukses pertandingan digunakan sebagai gantinya. Jadi kita punya

"anjing" =~ /d/; # 'd' cocok
"dogbert =~ //; # ini cocok dengan regexp 'd' yang digunakan sebelumnya

Aksi sesuai

Dua pengubah terakhir yang akan kita bahas di sini, "//g" dan "//c", menyangkut banyak kecocokan.
Pengubah "//g" adalah singkatan dari pencocokan global dan memungkinkan operator pencocokan untuk mencocokkan
dalam string sebanyak mungkin. Dalam konteks skalar, pemanggilan yang berurutan
terhadap string akan memiliki "//g" melompat dari pertandingan ke pertandingan, melacak posisi di
string saat berjalan. Anda bisa mendapatkan atau mengatur posisi dengan fungsi "pos()".

Penggunaan "//g" ditunjukkan pada contoh berikut. Misalkan kita memiliki string yang
terdiri dari kata-kata yang dipisahkan oleh spasi. Jika kita tahu berapa banyak kata sebelumnya, kita
dapat mengekstrak kata-kata menggunakan pengelompokan:

$x = "rumah anjing kucing"; # 3 kata
$x =~ /^\s*(\w+)\s+(\w+)\s+(\w+)\s*$/; # pertandingan,
# $1 = 'kucing'
# $2 = 'anjing'
# $3 = 'rumah'

Tetapi bagaimana jika kita memiliki jumlah kata yang tidak dapat ditentukan? Ini adalah jenis tugas "//g" itu
dibuat untuk. Untuk mengekstrak semua kata, bentuk regexp sederhana "(\w+)" dan ulangi semua kecocokan
dengan "/(\w+)/g":

sementara ($x =~ /(\w+)/g) {
print "Kata adalah $1, berakhir di posisi ", pos $x, "\n";
}

cetakan

Kata adalah kucing, berakhir di posisi 3
Word is dog, berakhir di posisi 7
Kata adalah rumah, berakhir di posisi 13

Kecocokan yang gagal atau mengubah string target mengatur ulang posisi. Jika Anda tidak ingin
reset posisi setelah gagal mencocokkan, tambahkan "//c", seperti pada "/ regexp/gc". Sekarang
posisi dalam string dikaitkan dengan string, bukan regexp. Ini berarti bahwa
string yang berbeda memiliki posisi yang berbeda dan posisi masing-masing dapat diatur atau
membaca secara mandiri.

Dalam konteks daftar, "//g" mengembalikan daftar pengelompokan yang cocok, atau jika tidak ada pengelompokan,
daftar kecocokan dengan seluruh regexp. Jadi jika kita hanya menginginkan kata-kata, kita bisa menggunakan

@kata = ($x =~ /(\w+)/g); # pertandingan,
# $words[0] = 'kucing'
# $kata[1] = 'anjing'
# $words[2] = 'rumah'

Terkait erat dengan pengubah "//g" adalah jangkar "\G". Jangkar "\ G" cocok di
titik di mana pertandingan "//g" sebelumnya berhenti. "\G" memungkinkan kita untuk dengan mudah melakukan konteks-
pencocokan sensitif:

$metrik = 1; # gunakan satuan metrik
...
$x = ; # baca dalam pengukuran
$x =~ /^([+-]?\d+)\s*/g; # dapatkan besaran
$berat = $1;
if ($metrik) { # pemeriksaan kesalahan
print "Kesalahan unit!" kecuali $x =~ /\Gkg\./g;
}
else {
print "Kesalahan unit!" kecuali $x =~ /\Glbs\./g;
}
$x =~ /\G\s+(widget|sproket)/g; # lanjutkan pemrosesan

Kombinasi "//g" dan "\G" memungkinkan kita untuk memproses string sedikit demi sedikit dan menggunakan
logika Perl sewenang-wenang untuk memutuskan apa yang harus dilakukan selanjutnya. Saat ini, jangkar "\G" hanya sepenuhnya
didukung saat digunakan untuk menambatkan ke awal pola.

"\G" juga sangat berharga dalam memproses catatan dengan panjang tetap dengan regexps. Misalkan kita memiliki
potongan DNA daerah pengkodean, dikodekan sebagai huruf pasangan basa "ATCGTTGAAT..." dan kami ingin
untuk menemukan semua kodon stop "TGA". Di wilayah pengkodean, kodon adalah urutan 3 huruf, jadi
kita dapat menganggap potongan DNA sebagai urutan catatan 3 huruf. Regexp naif

# diperluas, ini adalah "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC";
$dna =~ /TGA/;

tidak bekerja; itu mungkin cocok dengan "TGA", tetapi tidak ada jaminan bahwa kecocokan itu selaras
dengan batas kodon, misalnya, substring "GTT GAA" memberikan kecocokan. Solusi yang lebih baik adalah

while ($dna =~ /(\w\w\w)*?TGA/g) { # perhatikan minimal *?
print "Mendapat kodon stop TGA pada posisi ", pos $dna, "\n";
}

yang mencetak?

Mendapat kodon stop TGA di posisi 18
Mendapat kodon stop TGA di posisi 23

Posisi 18 bagus, tapi posisi 23 palsu. Apa yang terjadi?

Jawabannya adalah regexp kami berfungsi dengan baik sampai kami melewati pertandingan terakhir yang sebenarnya. Kemudian
regexp akan gagal mencocokkan "TGA" yang disinkronkan dan mulai melangkah maju satu karakter
posisi pada suatu waktu, bukan apa yang kita inginkan. Solusinya adalah menggunakan "\G" untuk menambatkan korek api ke
keselarasan kodon:

sementara ($dna =~ /\G(\w\w\w)*?TGA/g) {
print "Mendapat kodon stop TGA pada posisi ", pos $dna, "\n";
}

Ini mencetak

Mendapat kodon stop TGA di posisi 18

yang merupakan jawaban yang benar. Contoh ini menggambarkan bahwa penting tidak hanya untuk
mencocokkan apa yang diinginkan, tetapi menolak apa yang tidak diinginkan.

(Ada pengubah regexp lain yang tersedia, seperti "//o", tetapi spesialisasinya
penggunaan berada di luar cakupan pengantar ini. )

Pencarian dan menggantikan

Ekspresi reguler juga memainkan peran besar dalam Cari dan menggantikan operasi di Perl. Mencari
dan replace dilakukan dengan operator "s///". Bentuk umumnya adalah
"s/regexp/replacement/modifiers", dengan semua yang kami ketahui tentang regexps dan modifiers
berlaku dalam hal ini juga. "Pengganti" adalah string kutip ganda Perl yang
menggantikan dalam string apa pun yang cocok dengan "regexp". Operator "=~" juga
digunakan di sini untuk mengaitkan string dengan "s///". Jika cocok dengan $_, "$_ =~" dapat menjadi
menjatuhkan. Jika ada kecocokan, "s///" mengembalikan jumlah pergantian pemain yang dilakukan; sebaliknya
itu mengembalikan palsu. Berikut adalah beberapa contoh:

$x = "Waktunya memberi makan kucing!";
$x =~ s/cat/hacker/; # $x berisi "Waktunya memberi makan peretas!"
if ($x =~ s/^(Waktu.*peretas)!$/$1 sekarang!/) {
$more_insistent = 1;
}
$y = "'kata-kata yang dikutip'";
$y =~ s/^'(.*)'$/$1/; # strip tanda kutip tunggal,
# $y berisi "kata-kata yang dikutip"

Pada contoh terakhir, seluruh string dicocokkan, tetapi hanya bagian di dalam single
kutipan dikelompokkan. Dengan operator "s///", variabel yang cocok $1, $2, dll. adalah
segera tersedia untuk digunakan dalam ekspresi penggantian, jadi kami menggunakan $1 untuk menggantikan
dikutip string dengan hanya apa yang dikutip. Dengan pengubah global, "s///g" akan mencari
dan ganti semua kemunculan regexp dalam string:

$x = "Saya memukul 4 untuk 4";
$x =~ s/4/empat/; # tidak melakukan semuanya:
# $x berisi "Saya memukul empat untuk 4"
$x = "Saya memukul 4 untuk 4";
$x =~ s/4/empat/g; # melakukan semuanya:
# $x berisi "Saya memukul empat untuk empat"

Jika Anda lebih suka 'regex' daripada 'regexp' dalam tutorial ini, Anda dapat menggunakan program berikut
untuk menggantinya:

% cat > simple_replace
#!/usr/bin/Perl
$regexp = pergeseran;
$penggantian = shift;
sementara (<>) {
s/$regexp/$penggantian/g;
cetak;
}
^D

% simple_replace regexp regex perlretut.pod

Dalam "simple_replace" kami menggunakan pengubah "s///g" untuk mengganti semua kemunculan regexp
pada setiap baris. (Meskipun ekspresi reguler muncul dalam satu lingkaran, Perl cukup pintar
untuk mengompilasinya hanya sekali.) Seperti halnya "simple_grep", baik "print" dan
"s/$regexp/$replacement/g" gunakan $_ secara implisit.

Jika Anda tidak ingin "s///" mengubah variabel asli Anda, Anda dapat menggunakan non-destruktif
pengubah pengganti, "s///r". Ini mengubah perilaku sehingga "s///r" mengembalikan final
string yang diganti (bukan jumlah substitusi):

$x = "Saya suka anjing.";
$y = $x =~ s/anjing/kucing/r;
print "$x $y\n";

Contoh itu akan mencetak "Saya suka anjing. Saya suka kucing". Perhatikan variabel $x asli memiliki
tidak terpengaruh. Hasil keseluruhan dari substitusi malah disimpan di $y. jika
substitusi tidak memengaruhi apa pun maka string asli dikembalikan:

$x = "Saya suka anjing.";
$y = $x =~ s/gajah/cougars/r;
print "$x $y\n"; # mencetak "Saya suka anjing. Saya suka anjing."

Satu hal menarik lainnya yang diizinkan oleh flag "s///r" adalah substitusi berantai:

$x = "Kucing itu hebat.";
print $x =~ s/Kucing/Anjing/r =~ s/Anjing/Katak/r =~
s/Katak/Landak/r, "\n";
# mencetak "Landak itu hebat."

Pengubah yang tersedia secara khusus untuk mencari dan mengganti adalah evaluasi "s///e"
pengubah. "s///e" memperlakukan teks pengganti sebagai kode Perl, bukan tanda kutip ganda
rangkaian. Nilai yang dikembalikan kode diganti dengan substring yang cocok.
"s///e" berguna jika Anda perlu melakukan sedikit perhitungan dalam proses penggantian teks.
Contoh ini menghitung frekuensi karakter dalam satu baris:

$x = "Tagih kucing";
$x =~ s/(.)/$chars{$1}++;$1/mis; # final $1 menggantikan char dengan dirinya sendiri
print "frekuensi '$_' adalah $chars{$_}\n"
foreach (sort {$chars{$b} <=> kunci $chars{$a}} %chars);

Ini mencetak

frekuensi ' ' adalah 2
frekuensi 't' adalah 2
frekuensi 'l' adalah 2
frekuensi 'B' adalah 1
frekuensi 'c' adalah 1
frekuensi 'e' adalah 1
frekuensi 'h' adalah 1
frekuensi 'i' adalah 1
frekuensi 'a' adalah 1

Seperti operator pertandingan "m//", "s///" dapat menggunakan pembatas lain, seperti "s!!!" dan
"s{}{}", dan bahkan "s{}//". Jika tanda kutip tunggal digunakan "s'''", maka regexp dan
penggantian diperlakukan sebagai string yang dikutip tunggal dan tidak ada penggantian variabel.
"s///" dalam konteks daftar mengembalikan hal yang sama seperti dalam konteks skalar, yaitu jumlah
pertandingan.

membagi fungsi

Fungsi "split()" adalah tempat lain di mana regexp digunakan. "pecah /regexp/, string,
limit" memisahkan operan "string" ke dalam daftar substring dan mengembalikan daftar itu.
Regexp harus dirancang agar sesuai dengan apa pun yang merupakan pemisah untuk yang diinginkan
substring. "Batas", jika ada, batasan yang terpecah menjadi tidak lebih dari "batas"
jumlah string. Misalnya, untuk membagi string menjadi kata-kata, gunakan

$x = "Calvin dan Hobbes";
@kata = split /\s+/, $x; # $word[0] = 'Calvin'
# $kata[1] = 'dan'
# $word[2] = 'Hobbes'

Jika regexp kosong "//" digunakan, regexp selalu cocok dan string dipecah menjadi
karakter individu. Jika regexp memiliki pengelompokan, maka daftar yang dihasilkan berisi:
substring yang cocok dari pengelompokan juga. Contohnya,

$x = "/usr/bin/Perl";
@dirs = split m!/!, $x; # $dirs[0] = ''
# $dirs[1] = 'usr'
# $dirs[2] = 'bin'
# $dirs[3] = 'perl'
@bagian = split m!(/)!, $x; # $parts[0] = ''
# $bagian[1] = '/'
# $parts[2] = 'usr'
# $bagian[3] = '/'
# $bagian[4] = 'tempat sampah'
# $bagian[5] = '/'
# $parts[6] = 'perl'

Karena karakter pertama $x cocok dengan regexp, "split" diawali dengan inisial kosong
elemen ke daftar.

Jika Anda telah membaca sejauh ini, selamat! Anda sekarang memiliki semua alat dasar yang diperlukan untuk digunakan
ekspresi reguler untuk memecahkan berbagai masalah pemrosesan teks. Jika ini milikmu
pertama kali melalui tutorial, mengapa tidak berhenti di sini dan bermain-main dengan regexps a
sementara.... Bagian 2 menyangkut aspek yang lebih esoteris dari ekspresi reguler dan itu
konsep tentu tidak diperlukan di awal.

Bagian 2: Daya alat


Oke, Anda tahu dasar-dasar regexps dan ingin tahu lebih banyak. Jika cocok biasa
ekspresi dianalogikan dengan jalan-jalan di hutan, maka alat yang dibahas di Bagian 1 adalah
analog dengan peta topo dan kompas, alat dasar yang kita gunakan sepanjang waktu. Sebagian besar alat
di bagian 2 analog dengan senjata suar dan telepon satelit. Mereka tidak terlalu sering digunakan pada
pendakian, tetapi ketika kita terjebak, itu bisa sangat berharga.

Berikut ini adalah kemampuan Perl . yang lebih maju, jarang digunakan, atau terkadang esoteris
regexp. Di Bagian 2, kami akan menganggap Anda nyaman dengan dasar-dasarnya dan berkonsentrasi pada
fitur-fitur canggih.

More on karakter, string, dan karakter kelas-kelas
Ada beberapa urutan pelarian dan kelas karakter yang belum kita bahas.

Ada beberapa escape sequence yang mengubah karakter atau string antara upper dan
huruf kecil, dan mereka juga tersedia dalam pola. "\l" dan "\u" konversi berikutnya
karakter ke huruf kecil atau besar, masing-masing:

$x = "perl";
$string =~ /\u$x/; # cocok dengan 'Perl' di $string
$x = "M(rs?|s)\\."; # perhatikan garis miring terbalik ganda
$string =~ /\l$x/; # cocok dengan 'mr.', 'mrs.', dan 'ms.',

A "\L" atau "\U" menunjukkan konversi kasus yang bertahan lama, hingga diakhiri oleh "\E" atau dilemparkan
oleh "\U" atau "\L" lain:

$x = "Kata ini dalam huruf kecil:\L SHOUT\E";
$x =~ /teriak/; # pertandingan
$x = "SAYA MASIH MASIH KEYPUNCH KARTU UNTUK 360 SAYA"
$x =~ /\Ukeypunch/; # cocok dengan string kartu punch

Jika tidak ada "\E", huruf besar akan diubah hingga akhir string. regexps
"\L\u$word" atau "\u\L$word" mengubah karakter pertama $word menjadi huruf besar dan sisanya
dari karakter menjadi huruf kecil.

Karakter kontrol dapat diloloskan dengan "\c", sehingga karakter kontrol-Z akan menjadi
cocok dengan "\cZ". Urutan escape "\Q"..."\E" mengutip, atau melindungi sebagian besar non-
karakter alfabet. Contohnya,

$x = "\QItu !^*&%~& kucing!";
$x =~ /\Q!^*&%~&\E/; # periksa bahasa kasar

Itu tidak melindungi "$" atau "@", sehingga variabel masih bisa diganti.

"\Q", "\L", "\l", "\U", "\u" dan "\E" sebenarnya adalah bagian dari sintaks kutip ganda, dan bukan
bagian dari sintaks regexp yang tepat. Mereka akan berfungsi jika muncul dalam ekspresi reguler
disematkan secara langsung dalam sebuah program, tetapi tidak ketika terkandung dalam string yang diinterpolasi dalam
sebuah pola.

Regexps Perl dapat menangani lebih dari sekadar set karakter ASCII standar. Perl mendukung
Unicode, sebuah standar untuk mewakili abjad dari hampir seluruh dunia
bahasa tertulis, dan sejumlah simbol. String teks Perl adalah string Unicode, jadi
mereka dapat berisi karakter dengan nilai (titik kode atau nomor karakter) lebih tinggi dari 255.

Apa artinya ini untuk regexps? Nah, pengguna regexp tidak perlu tahu banyak tentang Perl's
representasi internal string. Tetapi mereka perlu tahu 1) cara mewakili Unicode
karakter dalam regexp dan 2) bahwa operasi pencocokan akan memperlakukan string menjadi
dicari sebagai urutan karakter, bukan byte. Jawaban untuk 1) adalah Unicode itu
karakter lebih besar dari "chr(255)" direpresentasikan menggunakan notasi "\x{hex}", karena
\x hex (tanpa kurung kurawal) tidak lebih dari 255. (Mulai dari Perl 5.14, jika
Anda adalah penggemar oktal, Anda juga dapat menggunakan "\o{oct}".)

/\x{263a}/; # cocok dengan wajah tersenyum Unicode :)

CATATAN: Di Perl 5.6.0 dulu orang perlu mengatakan "gunakan utf8" untuk menggunakan Unicode apa pun
fitur. Ini tidak lagi terjadi: untuk hampir semua pemrosesan Unicode, eksplisit
pragma "utf8" tidak diperlukan. (Satu-satunya kasus yang penting adalah jika skrip Perl Anda ada di
Unicode dan dikodekan dalam UTF-8, maka "gunakan utf8" eksplisit diperlukan.)

Mencari tahu urutan heksadesimal dari karakter Unicode yang Anda inginkan atau uraikan
regexp Unicode heksadesimal orang lain sama menyenangkannya dengan pemrograman di mesin
kode. Jadi cara lain untuk menentukan karakter Unicode adalah dengan menggunakan bernama karakter melarikan diri
urutan "\N{nama}". nama adalah nama untuk karakter Unicode, sebagaimana ditentukan dalam
Standar Unicode. Misalnya, jika kita ingin mewakili atau mencocokkan tanda astrologi
untuk planet Merkurius, kita bisa menggunakan

$x = "abc\N{MERCURY}def";
$x =~ /\N{MERCURY}/; # pertandingan

Seseorang juga dapat menggunakan nama "pendek":

print "\N{Yunani SMALL LETTER SIGMA} disebut sigma.\n";
print "\N{greek:Sigma} adalah sigma huruf besar.\n";

Anda juga dapat membatasi nama ke alfabet tertentu dengan menentukan pragma charnames:

gunakan charnames qw(yunani);
print "\N{sigma} adalah sigma Yunani\n";

Indeks nama karakter tersedia online dari Unicode Consortium,
<http://www.unicode.org/charts/charindex.html>; materi penjelasan dengan tautan ke yang lain
sumber daya dihttp://www.unicode.org/standard/where>.

Jawaban untuk persyaratan 2) adalah regexp (kebanyakan) menggunakan karakter Unicode. NS
"kebanyakan" adalah untuk alasan kompatibilitas mundur yang berantakan, tetapi mulai dari Perl 5.14, regex apa pun
dikompilasi dalam lingkup "gunakan fitur 'unicode_strings'" (yang secara otomatis berubah
pada dalam lingkup "gunakan 5.012" atau lebih tinggi) akan mengubah "kebanyakan" menjadi "selalu". Jika
Anda ingin menangani Unicode dengan benar, Anda harus memastikan bahwa 'unicode_strings' diaktifkan
pada. Secara internal, ini dikodekan ke byte menggunakan UTF-8 atau pengkodean 8 bit asli,
tergantung pada sejarah string, tetapi secara konseptual itu adalah urutan karakter,
bukan byte. Lihat perlunitut untuk tutorial tentang itu.

Sekarang mari kita bahas kelas karakter Unicode, yang paling sering disebut "properti karakter".
Ini diwakili oleh urutan escape "\p{name}". Terkait erat adalah
Properti "\P{name}", yang merupakan negasi dari properti "\p{name}". Misalnya, untuk mencocokkan
karakter huruf kecil dan besar,

$x = "BOB";
$x =~ /^\p{IsUpper}/; # kecocokan, kelas karakter huruf besar
$x =~ /^\P{IsUpper}/; # tidak cocok, kelas karakter tanpa huruf besar
$x =~ /^\p{IsLower}/; # tidak cocok, kelas karakter huruf kecil
$x =~ /^\P{IsLower}/; # cocok, kelas karakter tanpa huruf kecil

("Apakah" adalah opsional.)

Ada banyak, banyak properti karakter Unicode. Untuk daftar lengkapnya, lihat perluniprops.
Kebanyakan dari mereka memiliki sinonim dengan nama yang lebih pendek, juga terdaftar di sana. Beberapa sinonim adalah
karakter tunggal. Untuk ini, Anda bisa melepas kawat gigi. Misalnya, "\pM" adalah sama
hal sebagai "\p{Tandai}", yang berarti hal-hal seperti tanda aksen.

Properti Unicode "\p{Script}" digunakan untuk mengkategorikan setiap karakter Unicode ke dalam
skrip bahasa yang digunakan untuk menulis. Misalnya, bahasa Inggris, Prancis, dan banyak lainnya
Bahasa-bahasa Eropa ditulis dalam aksara Latin. Tapi ada juga tulisan Yunani,
aksara Thailand, aksara Katakana, dll. Anda dapat menguji apakah suatu karakter ada dalam a
skrip tertentu dengan, misalnya "\p{Latin}", "\p{Yunani}", atau "\p{Katakana}". Untuk mengetes
jika tidak dalam aksara Bali, gunakan "\P{Bali}".

Apa yang telah kami jelaskan sejauh ini adalah bentuk tunggal dari kelas karakter "\p{...}".
Ada juga bentuk majemuk yang mungkin Anda temui. Ini terlihat seperti "\p{name=value}" atau
"\p{name:value}" (tanda sama dengan dan titik dua dapat digunakan secara bergantian). Ini lebih
umum daripada bentuk tunggal, dan pada kenyataannya sebagian besar bentuk tunggal hanya didefinisikan Perl
jalan pintas untuk bentuk senyawa umum. Misalnya, contoh skrip di sebelumnya
paragraf dapat ditulis secara ekuivalen sebagai "\p{Script=Latin}", "\p{Script:Greek}",
"\p{script=katakana}", dan "\P{script=balinese}" (huruf besar tidak relevan antara "{}"
kawat gigi). Anda mungkin tidak pernah harus menggunakan bentuk majemuk, tetapi terkadang itu perlu, dan
penggunaannya dapat membuat kode Anda lebih mudah dipahami.

"\X" adalah singkatan untuk kelas karakter yang terdiri dari Unicode luas grafem
kelompok. Ini mewakili "karakter logis": apa yang tampak sebagai karakter tunggal,
tetapi dapat diwakili secara internal oleh lebih dari satu. Sebagai contoh, menggunakan Unicode full
nama, misalnya, "A + COMBINING RING" adalah cluster grafem dengan karakter dasar "A" dan
menggabungkan karakter "COMBINING RING", yang diterjemahkan dalam bahasa Denmark menjadi A dengan lingkaran di atas
itu, seperti dalam kata Aangstrom.

Untuk informasi lengkap dan terbaru tentang Unicode, lihat standar Unicode terbaru, atau
Situs web Konsorsium Unicodehttp://www.unicode.org>

Seolah-olah semua kelas itu tidak cukup, Perl juga mendefinisikan kelas karakter gaya POSIX.
Ini memiliki bentuk "[:name:]", dengan "name" nama kelas POSIX. POSIX
kelasnya adalah "alpha", "alnum", "ascii", "cntrl", "digit", "graph", "lower", "print",
"punct", "spasi", "atas", dan "xdigit", dan dua ekstensi, "word" (ekstensi Perl ke
cocok dengan "\w"), dan "kosong" (ekstensi GNU). Pengubah "//a" membatasi ini untuk
cocok hanya dalam kisaran ASCII; jika tidak, mereka dapat mencocokkan sama dengan yang sesuai
Kelas Perl Unicode: "[:upper:]" sama dengan "\p{IsUpper}", dll. (Ada beberapa
pengecualian dan gotcha dengan ini; lihat perlrecharclass untuk diskusi lengkap.)
"[:digit:]", "[:word:]", dan "[:spasi:]" sesuai dengan "\d", "\w", dan "\s" yang familiar
kelas karakter. Untuk meniadakan kelas POSIX, letakkan "^" di depan nama, sehingga,
misalnya, "[:^digit:]" sesuai dengan "\D" dan, di bawah Unicode, "\P{IsDigit}". Unicode dan
Kelas karakter POSIX dapat digunakan seperti "\d", dengan pengecualian bahwa POSIX
kelas karakter hanya dapat digunakan di dalam kelas karakter:

/\s+[abc[:digit:]xyz]\s*/; # cocokkan a,b,c,x,y,z, atau angka
/^=item\s[[:digit:]]/; # cocokkan '=item',
# diikuti dengan spasi dan angka
/\s+[abc\p{IsDigit}xyz]\s+/; # cocokkan a,b,c,x,y,z, atau angka
/^=item\s\p{IsDigit}/; # cocokkan '=item',
# diikuti dengan spasi dan angka

Wah! Itu semua karakter dan kelas karakter lainnya.

kompilasi dan penghematan reguler ekspresi
Di Bagian 1 kami menyebutkan bahwa Perl mengkompilasi regexp ke dalam urutan opcode yang ringkas.
Dengan demikian, regexp yang dikompilasi adalah struktur data yang dapat disimpan sekali dan digunakan lagi dan
lagi. Kutipan regexp "qr//" melakukan hal itu: "qr/string/" mengkompilasi "string" sebagai
regexp dan mengubah hasilnya menjadi bentuk yang dapat ditetapkan ke variabel:

$reg = qr/foo+bar?/; # reg berisi regexp yang dikompilasi

Kemudian $reg dapat digunakan sebagai regexp:

$x = "fooooba";
$x =~ $reg; # cocok, seperti /foo+bar?/
$x =~ /$reg/; # hal yang sama, bentuk alternatif

$reg juga dapat diinterpolasi menjadi regexp yang lebih besar:

$x =~ /(abc)?$reg/; #masih cocok

Seperti operator yang cocok, kutipan regexp dapat menggunakan pembatas yang berbeda, misalnya,
"qr!!", "qr{}" atau "qr~~". Apostrof sebagai pembatas ("qr''") menghambat interpolasi apapun.

Regexp yang telah dikompilasi sebelumnya berguna untuk membuat kecocokan dinamis yang tidak perlu
dikompilasi ulang setiap kali mereka ditemui. Menggunakan regexp yang telah dikompilasi sebelumnya, kami menulis a
program "grep_step" yang mengambil urutan pola, melanjutkan ke pola berikutnya
segera setelah seseorang merasa puas.

% kucing > grep_step
#!/usr/bin/Perl
# grep_step - cocokkan regexps, satu demi satu
# penggunaan: multi_grep regexp1 regexp2 ... file1 file2 ...

$angka = pergeseran;
$regexp[$_] = shift foreach (0..$angka-1);
@kompilasi = peta qr/$_/, @regexp;
while ($baris = <>) {
if ($baris =~ /$dikompilasi[0]/) {
cetak $baris;
shift @dikompilasi;
terakhir kecuali @ dikompilasi;
}
}
^D

% grep_step 3 shift cetak grep_step terakhir
$angka = pergeseran;
cetak $baris;
terakhir kecuali @ dikompilasi;

Menyimpan regexp yang telah dikompilasi sebelumnya dalam sebuah array @compiled memungkinkan kita untuk hanya mengulang melalui
regexps tanpa kompilasi ulang, sehingga mendapatkan fleksibilitas tanpa mengorbankan kecepatan.

Menulis reguler ekspresi at runtime
Backtracking lebih efisien daripada percobaan berulang dengan ekspresi reguler yang berbeda. Jika
ada beberapa ekspresi reguler dan kecocokan dengan salah satu dari mereka dapat diterima, maka itu
adalah mungkin untuk menggabungkan mereka menjadi satu set alternatif. Jika ekspresi individu adalah
input data, ini dapat dilakukan dengan memprogram operasi join. Kami akan mengeksploitasi ide ini di
versi perbaikan dari program "simple_grep": program yang cocok dengan beberapa
pola:

% kucing > multi_grep
#!/usr/bin/Perl
# multi_grep - cocok dengan salah satu dari regexps
# penggunaan: multi_grep regexp1 regexp2 ... file1 file2 ...

$angka = pergeseran;
$regexp[$_] = shift foreach (0..$angka-1);
$pattern = gabung '|', @regexp;

while ($baris = <>) {
print $baris jika $baris =~ /$pattern/;
}
^D

% multi_grep 2 shift untuk multi_grep
$angka = pergeseran;
$regexp[$_] = shift foreach (0..$angka-1);

Terkadang menguntungkan untuk membangun pola dari memasukkan yang akan dianalisis
dan gunakan nilai yang diizinkan di sisi kiri operasi pencocokan. sebagai
contoh untuk situasi yang agak paradoks ini, mari kita asumsikan bahwa input kita mengandung a
kata kerja perintah yang harus cocok dengan satu dari serangkaian kata kerja perintah yang tersedia, dengan
twist tambahan bahwa perintah dapat disingkat selama string yang diberikan unik.
Program di bawah ini menunjukkan algoritma dasar.

% kucing > keymatch
#!/usr/bin/Perl
$kwds = 'salin cetak daftar perbandingan';
sementara( $cmd = <> ){
$cmd =~ s/^\s+|\s+$//g; # memangkas spasi awal dan akhir
jika( ( @pertandingan = $kwds =~ /\b$cmd\w*/g ) == 1 ){
print "perintah: '@matches'\n";
} elsif( @cocok == 0 ){
print "tidak ada perintah seperti itu: '$cmd'\n";
} Else {
print "tidak unik: '$cmd' (bisa salah satu dari: @matches)\n";
}
}
^D

% pencocokan kunci
li
perintah: 'daftar'
co
tidak unik: 'co' (bisa salah satu dari: salin bandingkan)
pencetak
tidak ada perintah seperti itu: 'printer'

Daripada mencoba mencocokkan input dengan kata kunci, kami mencocokkan kumpulan gabungan
kata kunci terhadap input. Operasi pencocokan pola "$kwds =~ /\b($cmd\w*)/g" tidak
beberapa hal sekaligus. Itu memastikan bahwa perintah yang diberikan dimulai di mana a
kata kunci dimulai ("\b"). Ini mentolerir singkatan karena ditambahkan "\w*". Ini memberitahu kita
jumlah kecocokan ("scalar @matches") dan semua kata kunci yang benar-benar cocok.
Anda hampir tidak bisa meminta lebih banyak.

Menanamkan komentar dan pengubah in a reguler ekspresi
Dimulai dengan bagian ini, kita akan membahas himpunan Perl luas pola. Ini
adalah ekstensi ke sintaks ekspresi reguler tradisional yang memberikan kekuatan baru
alat untuk pencocokan pola. Kami telah melihat ekstensi dalam bentuk minimal
pencocokan konstruksi "??", "*?", "+?", "{n,m}?", dan "{n,}?". Sebagian besar ekstensi di bawah ini
memiliki bentuk "(?char...)", dimana "char" adalah karakter yang menentukan jenis
perpanjangan.

Ekstensi pertama adalah komentar tersemat "(?#teks)". Ini menyematkan komentar ke dalam
ekspresi reguler tanpa mempengaruhi maknanya. Komentar seharusnya tidak memiliki penutup
tanda kurung dalam teks. Contohnya adalah

/(?# Mencocokkan bilangan bulat :)[+-]?\d+/;

Gaya berkomentar ini sebagian besar telah digantikan oleh komentar mentah dan bentuk bebas yang
diperbolehkan dengan pengubah "//x".

Kebanyakan pengubah, seperti "//i", "//m", "//s" dan "//x" (atau kombinasinya) dapat
juga disematkan dalam regexp menggunakan "(?i)", "(?m)", "(?s)", dan "(?x)". Contohnya,

/(?saya iya/; # cocokkan huruf 'ya' dengan tidak peka
/ya saya; # hal yang sama
/(?x)( # versi bentuk bebas dari regexp bilangan bulat
[+-]? # cocok dengan tanda opsional
\d+ # cocok dengan urutan digit
)
/X;

Pengubah tertanam dapat memiliki dua keunggulan penting dibandingkan pengubah biasa. Tertanam
pengubah memungkinkan satu set pengubah khusus untuk setiap pola regexp. Ini bagus untuk
mencocokkan larik regexp yang harus memiliki pengubah berbeda:

$pattern[0] = '(?i)dokter';
$pola[1] = 'Johnson';
...
sementara (<>) {
foreach $patt (@pattern) {
cetak jika /$patt/;
}
}

Keuntungan kedua adalah pengubah yang disematkan (kecuali "//p", yang memodifikasi keseluruhan
regexp) hanya memengaruhi regexp di dalam grup tempat pengubah tersemat berada. Jadi
pengelompokan dapat digunakan untuk melokalisasi efek pengubah:

/Jawaban: ((?i)ya)/; # cocok dengan 'Jawaban: ya', 'Jawab: YA', dll.

Pengubah tersemat juga dapat mematikan pengubah yang sudah ada dengan menggunakan, misalnya,
"(?-Saya)". Pengubah juga dapat digabungkan menjadi satu ekspresi, misalnya, "(?si)" menyala
mode satu baris dan menonaktifkan ketidakpekaan huruf besar/kecil.

Pengubah yang disematkan juga dapat ditambahkan ke pengelompokan yang tidak menangkap. "(?im:regexp)" adalah
pengelompokan tidak menangkap yang cocok dengan huruf besar "regexp" secara tidak sensitif dan mematikan multi-baris
mode.

Mencari di depan dan mencari di belakang
Bagian ini menyangkut pernyataan pandangan ke depan dan pandangan ke belakang. Pertama, sedikit
latar belakang.

Dalam ekspresi reguler Perl, sebagian besar elemen regexp 'memakan' sejumlah string ketika
mereka cocok. Misalnya, elemen regexp "[abc}]" memakan satu karakter string
ketika cocok, dalam arti Perl pindah ke posisi karakter berikutnya dalam string
setelah pertandingan. Namun, ada beberapa elemen yang tidak memakan karakter (maju
posisi karakter) jika cocok. Contoh yang telah kita lihat sejauh ini adalah jangkar.
Jangkar "^" cocok dengan awal baris, tetapi tidak memakan karakter apa pun.
Demikian pula, jangkar batas kata "\b" cocok di mana pun karakter yang cocok dengan "\w" berada
di sebelah karakter yang tidak, tetapi tidak memakan karakter itu sendiri. Jangkar
adalah contoh dari lebar nol pernyataan: lebar nol, karena tidak menggunakan karakter, dan
pernyataan, karena mereka menguji beberapa properti string. Dalam konteks perjalanan kami
analogi hutan dengan pencocokan regexp, sebagian besar elemen regexp menggerakkan kita di sepanjang jalan, tapi
jangkar membuat kita berhenti sejenak dan memeriksa sekeliling kita. Jika lingkungan setempat memeriksa
keluar, kita bisa melanjutkan ke depan. Tetapi jika lingkungan setempat tidak memuaskan kita, kita harus
mundur.

Memeriksa lingkungan memerlukan baik melihat ke depan di jalan setapak, melihat ke belakang, atau
keduanya. "^" melihat ke belakang, untuk melihat bahwa tidak ada karakter sebelumnya. "$" melihat ke depan, untuk
lihat bahwa tidak ada karakter setelahnya. "\b" melihat ke depan dan ke belakang, untuk melihat apakah
karakter di kedua sisi berbeda dalam "kata-kata" mereka.

Pernyataan lookahead dan lookbehind adalah generalisasi dari konsep jangkar.
Lihat ke depan dan lihat ke belakang adalah pernyataan lebar nol yang memungkinkan kita menentukan karakter mana yang kita
ingin menguji. Pernyataan lookahead dilambangkan dengan "(?=regexp)" dan lookbehind
pernyataan dilambangkan dengan "(?<=fixed-regexp)". Beberapa contohnya adalah

$x = "Saya menangkap kucing rumahan 'Tom-cat' dengan catnip";
$x =~ /cat(?=\s)/; # cocok dengan 'kucing' di 'kucing rumah'
@catwords = ($x =~ /(?<=\s)cat\w+/g); # pertandingan,
# $catwords[0] = 'tangkap'
# $catwords[1] = 'catnip'
$x =~ /\bcat\b/; # cocok dengan 'kucing' di 'Tom-cat'
$x =~ /(?<=\s)cat(?=\s)/; # tidak cocok; tidak ada 'kucing' yang terisolasi di
# tengah $x

Perhatikan bahwa tanda kurung di "(?=regexp)" dan "(?<=regexp)" tidak digunakan, karena ini
adalah pernyataan lebar-nol. Jadi di regexp kedua, substring yang ditangkap adalah
dari seluruh regexp itu sendiri. Lookahead "(?=regexp)" dapat mencocokkan regexp yang berubah-ubah, tetapi
lihat di belakang "(?<=fixed-regexp)" hanya berfungsi untuk regexp dengan lebar tetap, yaitu, nomor tetap
dari karakter panjang. Jadi "(?<=(ab|bc))" baik-baik saja, tetapi "(?<=(ab)*)" tidak. yang dinegasikan
versi pernyataan lookahead dan lookbehind dilambangkan dengan "(?!regexp)" dan
"(? tidak cocok:

$x = "bilah kaki";
$x =~ /foo(?!bar)/; # tidak cocok, 'bar' mengikuti 'foo'
$x =~ /foo(?!baz)/; # cocok, 'baz' tidak mengikuti 'foo'
$x =~ /(?

"\C" tidak didukung di tampilan belakang, karena definisi "\C" yang sudah berbahaya
akan menjadi lebih ketika akan mundur.

Berikut adalah contoh di mana string yang berisi kata-kata, angka, dan tunggal yang dipisahkan kosong
tanda hubung harus dipecah menjadi komponen-komponennya. Menggunakan "/\s+/" saja tidak akan berfungsi, karena spasi
tidak diperlukan antara tanda hubung, atau kata atau tanda hubung. Tempat tambahan untuk split adalah
didirikan dengan melihat ke depan dan ke belakang:

$str = "satu dua - --6-8";
@toks = split / \s+ # lari spasi
| (?<=\S) (?=-) # sembarang non-spasi diikuti oleh '-'
| (?<=-) (?=\S) # a '-' diikuti oleh non-spasi
/x, $str; # @toks = qw(satu dua - - - 6 - 8)

Menggunakan independen subekspresi untuk mencegah mundur
Independen subekspresi adalah ekspresi reguler, dalam konteks reguler yang lebih besar
ekspresi, yang berfungsi secara independen dari ekspresi reguler yang lebih besar. Artinya, mereka
mengkonsumsi string sebanyak atau sesedikit yang mereka inginkan tanpa memperhatikan kemampuan
regexp yang lebih besar untuk dicocokkan. Subekspresi independen diwakili oleh "(?>regexp)".
Kita dapat mengilustrasikan perilaku mereka dengan terlebih dahulu mempertimbangkan regexp biasa:

$x = "ab";
$x =~ /a*ab/; # pertandingan

Ini jelas cocok, tetapi dalam proses pencocokan, subekspresi "a*" terlebih dahulu
meraih "a". Melakukannya, bagaimanapun, tidak akan membuat seluruh regexp cocok, jadi setelahnya
mundur, "a*" akhirnya mengembalikan "a" dan mencocokkan string kosong. Di sini, apa?
"a*" yang cocok adalah tergantung pada apa yang cocok dengan regexp lainnya.

Bandingkan dengan subekspresi independen:

$x =~ /(?>a*)ab/; # tidak cocok!

Subekspresi independen "(?>a*)" tidak peduli dengan sisa regexp, jadi
melihat "a" dan meraihnya. Kemudian sisa regexp "ab" tidak dapat cocok. Karena
"(?>a*)" adalah independen, tidak ada backtracking dan subekspresi independen tidak
tidak menyerah "a". Dengan demikian kecocokan regexp secara keseluruhan gagal. Perilaku serupa
terjadi dengan regexps yang sepenuhnya independen:

$x = "ab";
$x =~ /a*/g; # cocok, makan 'a'
$x =~ /\Gab/g; # tidak cocok, tidak ada 'a' yang tersedia

Di sini "//g" dan "\G" membuat serah terima string 'tim tag' dari satu regexp ke
lainnya. Regexps dengan subekspresi independen seperti ini, dengan handoff
string ke subekspresi independen, dan serah terima string kembali ke
melampirkan regexp.

Kemampuan subekspresi independen untuk mencegah backtracking bisa sangat berguna.
Misalkan kita ingin mencocokkan string tidak kosong yang diapit tanda kurung hingga kedalaman dua level.
Kemudian regexp berikut cocok:

$x = "abc(de(fg)h"; # tanda kurung tidak seimbang
$x =~ /\( ( [^()]+ | \([^()]*\) )+ \)/x;

Regexp cocok dengan tanda kurung buka, satu atau lebih salinan alternasi, dan tanda kurung tutup
kurung. Pergantian adalah dua arah, dengan alternatif pertama "[^()]+" cocok dengan a
substring tanpa tanda kurung dan alternatif kedua "\([^()]*\)" cocok a
substring yang dibatasi oleh tanda kurung. Masalah dengan regexp ini adalah
patologis: ia memiliki kuantor tak tentu bersarang dari bentuk "(a+|b)+". Kami berdiskusi
di Bagian 1 bagaimana quantifier bersarang seperti ini membutuhkan waktu yang sangat lama untuk
mengeksekusi jika tidak ada kecocokan yang mungkin. Untuk mencegah ledakan eksponensial, kita perlu
mencegah kemunduran yang tidak berguna di beberapa titik. Ini dapat dilakukan dengan melampirkan bagian dalam
quantifier sebagai subekspresi independen:

$x =~ /\( ( (?>[^()]+) | \([^()]*\) )+ \)/x;

Di sini, "(?>[^()]+)" memecah degenerasi partisi string dengan melahap sebanyak
string mungkin dan menjaganya. Kemudian kegagalan pencocokan gagal jauh lebih cepat.

Bersyarat ekspresi
A bersyarat ekspresi adalah bentuk pernyataan if-then-else yang memungkinkan seseorang untuk memilih
pola mana yang harus dicocokkan, berdasarkan beberapa kondisi. Ada dua jenis
ekspresi bersyarat: "(?(kondisi)ya-regexp)" and
"(?(kondisi)ya-regexp|tidak-regexp)". "(?(condition)yes-regexp)" seperti 'if () {}'
pernyataan dalam Perl. Jika "kondisi" benar, "ya-regexp" akan cocok. jika
"kondisi" salah, "ya-regexp" akan dilewati dan Perl akan pindah ke yang berikutnya
elemen regexp. Bentuk kedua seperti pernyataan 'if () {} else {}' di Perl. jika
"kondisi" benar, "yes-regexp" akan cocok, jika tidak, "no-regexp" akan menjadi
cocok.

"Kondisi" dapat memiliki beberapa bentuk. Bentuk pertama hanyalah bilangan bulat dalam
tanda kurung "(bilangan bulat)". Memang benar jika referensi balik yang sesuai "\integer" cocok
sebelumnya di regexp. Hal yang sama dapat dilakukan dengan nama yang terkait dengan penangkapan
kelompok, ditulis sebagai "( )" atau "('nama')". Bentuk kedua adalah lebar nol bare
pernyataan "(?...)", baik melihat ke depan, melihat ke belakang, atau pernyataan kode (dibahas di
bagian berikutnya). Kumpulan formulir ketiga menyediakan pengujian yang mengembalikan nilai true jika:
ekspresi dieksekusi dalam rekursi ("(R)") atau dipanggil dari beberapa penangkapan
grup, direferensikan dengan nomor ("(R1)", "(R2)",...) atau dengan nama ("(R&nama)").

Bentuk bilangan bulat atau nama dari "kondisi" memungkinkan kita untuk memilih, dengan lebih fleksibel,
apa yang cocok berdasarkan apa yang cocok sebelumnya di regexp. Ini mencari kata-kata dari
bentuk "$x$x" atau "$x$y$y$x":

% simple_grep '^(\w+)(\w+)?(?(2)\g2\g1|\g1)$' /usr/dict/words
beri-beri
kelapa
couscous
perbuatan
...
tiupan
toto
tutu

Tampilan di belakang "kondisi" memungkinkan, bersama dengan referensi balik, bagian awal pertandingan
untuk mempengaruhi bagian selanjutnya dari pertandingan. Contohnya,

/[ATGC]+(?(?<=AA)G|C)$/;

cocok dengan urutan DNA sedemikian rupa sehingga berakhir dengan "AAG", atau pasangan basa lainnya
kombinasi dan "C". Perhatikan bahwa bentuknya adalah "(?(?<=AA)G|C)" dan bukan "(?((?<=AA))G|C)"; untuk
pernyataan lookahead, lookbehind atau kode, tanda kurung di sekitar conditional adalah
tidak dibutuhkan.

Mendefinisikan bernama pola
Beberapa ekspresi reguler menggunakan subpola yang identik di beberapa tempat. Dimulai dengan Perl
5.10, dimungkinkan untuk mendefinisikan subpola bernama di bagian pola sehingga mereka
dapat dipanggil dengan nama di mana saja dalam pola. Pola sintaksis ini untuk ini
grup definisi adalah "(?(DEFINE)(? pattern)...)". Sisipan dari pola bernama adalah
ditulis sebagai "(?&nama)".

Contoh di bawah mengilustrasikan fitur ini menggunakan pola untuk bilangan floating point
yang disajikan sebelumnya. Tiga subpola yang digunakan lebih dari sekali adalah
tanda opsional, urutan digit untuk bilangan bulat dan pecahan desimal. DEFINISI
kelompok di akhir pola berisi definisi mereka. Perhatikan bahwa desimal
pola pecahan adalah tempat pertama di mana kita dapat menggunakan kembali pola bilangan bulat.

/^ (?&osg)\ * ( (?&int)(?&des)? | (?&des) )
(?: [eE](?&osg)(?&int) )?
$
(?(MENDEFINISIKAN)
(? [-+]?) # tanda opsional
(? \d++) # bilangan bulat
(? \.(?&int)) # pecahan desimal
)/X

Rekursif pola
Fitur ini (diperkenalkan di Perl 5.10) secara signifikan memperluas kekuatan pola Perl
cocok. Dengan mengacu pada beberapa grup tangkap lain di mana saja dalam pola dengan
membangun "(?grup-ref)", the belt hold dalam kelompok yang direferensikan digunakan sebagai
subpola independen menggantikan referensi grup itu sendiri. Karena kelompok
referensi mungkin terkandung dalam grup yang dirujuk, sekarang mungkin untuk mendaftar
pencocokan pola dengan tugas-tugas yang sampai sekarang membutuhkan parser rekursif.

Untuk mengilustrasikan fitur ini, kami akan mendesain pola yang cocok jika string berisi
palindrom. (Ini adalah kata atau kalimat yang, sementara mengabaikan spasi, interpunctuation
dan kasus, membaca mundur sama seperti ke depan. Kita mulai dengan mengamati bahwa yang kosong
string atau string yang hanya berisi satu karakter kata adalah palindrom. Kalau tidak, itu harus
memiliki karakter kata di depan dan sama di akhir, dengan palindrom lain di
antara.

/(?: (\w) (?...Ini palindrom...) \g{-1} | \w? )/x

Menambahkan "\W*" di kedua ujungnya untuk menghilangkan apa yang harus diabaikan, kita sudah memiliki yang lengkap
pola:

$pp saya = qr/^(\W* (?: (\w) (?1) \g{-1} | \w? ) \W*)$/ix;
for $s ( "saippuakauppias", "Seorang pria, sebuah rencana, sebuah kanal: Panama!" ){
print "'$s' adalah palindrom\n" jika $s =~ /$pp/;
}

Dalam "(?...)" referensi balik absolut dan relatif dapat digunakan. Seluruh pola bisa
dimasukkan kembali dengan "(?R)" atau "(?0)". Jika Anda lebih suka menamai grup Anda, Anda dapat menggunakan
"(?&nama)" untuk berulang ke grup itu.

A sedikit of sihir: mengeksekusi Perl kode in a reguler ekspresi
Biasanya, regexps adalah bagian dari ekspresi Perl. Kode evaluasi ekspresi berubah itu
sekitar dengan mengizinkan kode Perl sewenang-wenang menjadi bagian dari regexp. Evaluasi kode
ekspresi dilambangkan "(?{code})", dengan kode serangkaian pernyataan Perl.

Berhati-hatilah bahwa fitur ini dianggap eksperimental, dan dapat diubah tanpa pemberitahuan.

Ekspresi kode adalah pernyataan lebar nol, dan nilai yang mereka kembalikan bergantung pada
lingkungan. Ada dua kemungkinan: ekspresi kode digunakan sebagai
kondisional dalam ekspresi kondisional "(?(kondisi)...)", atau tidak. Jika kode
ekspresi bersyarat, kode dievaluasi dan hasilnya (yaitu, hasil dari
pernyataan terakhir) digunakan untuk menentukan kebenaran atau kepalsuan. Jika ekspresi kode tidak
digunakan sebagai kondisi, pernyataan selalu mengevaluasi benar dan hasilnya dimasukkan ke dalam
variabel khusus $^R. Variabel $^R kemudian dapat digunakan dalam ekspresi kode nanti di
reg. Berikut adalah beberapa contoh konyol:

$x = "abcdef";
$x =~ /abc(?{print "Hai Bu!";})def/; # pertandingan,
# mencetak 'Hai Bu!'
$x =~ /aaa(?{print "Hai Bu!";})def/; # tidak cocok,
# tidak 'Hai Bu!'

Perhatikan baik-baik contoh berikut:

$x =~ /abc(?{print "Hai Bu!";})ddd/; # tidak cocok,
# tidak 'Hai Bu!'
# Namun mengapa tidak?

Pada pandangan pertama, Anda akan berpikir bahwa itu tidak boleh dicetak, karena jelas "ddd" tidak
akan cocok dengan string target. Tapi lihat contoh ini:

$x =~ /abc(?{print "Hai Bu!";})[dD]dd/; # tidak cocok,
# tapi _tidak_ mencetak

Hmm. Apa yang terjadi disini? Yang udah ngikutin pasti tau pola di atas
harus efektif (hampir) sama dengan yang terakhir; melampirkan "d" dalam karakter
kelas tidak akan mengubah apa yang cocok. Jadi mengapa yang pertama tidak mencetak sementara
yang kedua bisa?

Jawabannya terletak pada optimasi yang dibuat oleh mesin regex. Dalam kasus pertama, semua
tampilan mesin adalah karakter lama biasa (selain dari konstruksi "?{}"). Cukup pintar
untuk menyadari bahwa string 'ddd' tidak muncul di string target kami sebelumnya
menjalankan pola melalui. Tetapi dalam kasus kedua, kami telah menipunya dengan berpikir bahwa
pola kita lebih rumit. Dibutuhkan melihat, melihat kelas karakter kita, dan memutuskan
bahwa itu harus benar-benar menjalankan pola untuk menentukan apakah itu cocok atau tidak, dan
dalam proses menjalankannya, ia menyentuh pernyataan cetak sebelum menemukan bahwa kita tidak melakukannya
memiliki kecocokan.

Untuk melihat lebih dekat bagaimana mesin melakukan pengoptimalan, lihat bagian "Pragma dan
debug" di bawah.

Lebih menyenangkan dengan "?{}":

$x =~ /(?{print "Hai Bu!";})/; # pertandingan,
# mencetak 'Hai Bu!'
$x =~ /(?{$c = 1;})(?{cetak "$c";})/; # pertandingan,
# mencetak '1'
$x =~ /(?{$c = 1;})(?{cetak "$^R";})/; # pertandingan,
# mencetak '1'

Sedikit keajaiban yang disebutkan dalam judul bagian terjadi ketika regexp mundur di
proses mencari kecocokan. Jika regexp mundur melalui ekspresi kode dan jika
variabel yang digunakan dilokalisasi menggunakan "lokal", perubahan dalam variabel
dihasilkan oleh ekspresi kode dibatalkan! Jadi, jika kita ingin menghitung berapa kali a
karakter dicocokkan di dalam grup, kita bisa menggunakan, misalnya,

$x = "aaa";
$hitung = 0; # inisialisasi hitungan 'a'
$c = "bob"; # uji apakah $c dimusnahkan
$x =~ /(?{local $c = 0;}) # inisialisasi hitungan
( sebuah # cocok dengan 'a'
(?{local $c = $c + 1;}) # jumlah kenaikan
)* # lakukan ini beberapa kali,
aa # tapi cocokkan 'aa' di akhir
(?{$count = $c;}) # salin lokal $c var ke $count
/X;
print "'a' count adalah $count, \$c variabel adalah '$c'\n";

Ini mencetak

'a' count adalah 2, variabel $c adalah 'bob'

Jika kita mengganti " (?{local $c = $c + 1;})" dengan " (?{$c = $c + 1;})", variabel
perubahan adalah tidak dibatalkan selama backtracking, dan kami mendapatkan

'a' count adalah 4, variabel $c adalah 'bob'

Perhatikan bahwa hanya perubahan variabel lokal yang dibatalkan. Efek samping lain dari kode
eksekusi ekspresi bersifat permanen. Dengan demikian

$x = "aaa";
$x =~ /(a(?{print "Yow\n";}))*aa/;

menghasilkan

Yow
Yow
Yow
Yow

Hasilnya $^R secara otomatis dilokalkan, sehingga akan berperilaku baik di hadapan
dari mundur.

Contoh ini menggunakan ekspresi kode dalam kondisi untuk mencocokkan artikel tertentu, baik
'the' dalam bahasa Inggris atau 'der|die|das' dalam bahasa Jerman:

$lang = 'DE'; # gunakan bahasa Jerman
...
$teks = "das";
cetak "cocok\n"
jika $teks =~ /(?(?{
$lang eq 'EN'; # apakah bahasa inggris?
})
| # jika demikian, maka cocokkan dengan 'the'
(der|die|das) # lain, cocokkan 'der|die|das'
)
/xi;

Perhatikan bahwa sintaks di sini adalah "(?(?{...})yes-regexp|no-regexp)", bukan
"(?((?{...}))ya-regexp|tidak-regexp)". Dengan kata lain, dalam kasus ekspresi kode, kita
tidak perlu tanda kurung tambahan di sekitar conditional.

Jika Anda mencoba menggunakan ekspresi kode di mana teks kode terkandung dalam interpolasi
variabel, daripada muncul secara harfiah dalam pola, Perl mungkin mengejutkan Anda:

$batang = 5;
$pat = '(?{ 1 })';
/foo(?{ $bar })bar/; # kompilasi ok, $bar tidak diinterpolasi
/foo(?{ 1 })$bar/; # kompilasi ok, $bar diinterpolasi
/foo${pat}bar/; # kesalahan kompilasi!

$pat = qr/(?{ $foo = 1 })/; # kode prakompilasi regexp
/foo${pat}bar/; # kompilasi ok

Jika regexp memiliki variabel yang menginterpolasi ekspresi kode, Perl memperlakukan regexp sebagai
sebuah kesalahan. Jika ekspresi kode dikompilasi menjadi variabel, bagaimanapun, interpolasi adalah
oke. Pertanyaannya, kenapa ini error?

Alasannya adalah interpolasi variabel dan ekspresi kode bersama-sama menimbulkan keamanan
mempertaruhkan. Kombinasi ini berbahaya karena banyak programmer yang menulis mesin pencari
sering mengambil input pengguna dan menghubungkannya langsung ke regexp:

$regexp = <>; # baca regexp yang disediakan pengguna
$chomp $regexp; # singkirkan kemungkinan baris baru
$teks =~ /$regexp/; # cari $teks untuk $regexp

Jika variabel $regexp berisi ekspresi kode, pengguna kemudian dapat mengeksekusi arbitrer
kode Perl. Misalnya, beberapa joker dapat mencari "system('rm -rf *');" untuk menghapusmu
file. Dalam pengertian ini, kombinasi interpolasi dan ekspresi kode noda Tujuan
reg. Jadi secara default, menggunakan interpolasi dan ekspresi kode dalam regexp yang sama
tidak diizinkan. Jika Anda tidak khawatir tentang pengguna jahat, Anda dapat melewati
pemeriksaan keamanan ini dengan menjalankan "use re 'eval'":

gunakan re 'eval'; # buang hati-hati keluar pintu
$batang = 5;
$pat = '(?{ 1 })';
/foo${pat}bar/; # kompilasi ok

Bentuk lain dari ekspresi kode adalah belt hold kode ekspresi. Kode pola
ekspresi seperti ekspresi kode biasa, kecuali bahwa hasil kode
evaluasi diperlakukan sebagai ekspresi reguler dan segera dicocokkan. Contoh sederhana
is

$panjang = 5;
$char = 'a';
$x = 'aaaaabb';
$x =~ /(??{$char x $panjang})/x; # cocok, ada 5 'a'

Contoh terakhir ini berisi ekspresi kode biasa dan kode pola. Ini mendeteksi
apakah string biner 1101010010001... memiliki jarak Fibonacci 0,1,1,2,3,5,...
1:

$x = "1101010010001000001";
$z0 = ''; $z1 = '0'; # kondisi awal
print "Ini adalah barisan Fibonacci\n"
jika $x =~ /^1 # cocok dengan inisial '1'
(?:
((??{ $z0 })) # cocok dengan beberapa '0'
1 # dan kemudian '1'
(?{ $z0 = $z1; $z1 .= $^N; })
)+ # ulangi sesuai kebutuhan
$# hanya itu yang ada
/X;
printf "Urutan terbesar yang cocok adalah %d\n", length($z1)-length($z0);

Ingat bahwa $^N disetel ke apa pun yang cocok dengan grup tangkapan terakhir yang diselesaikan. Ini
cetakan

Itu adalah barisan Fibonacci
Urutan terbesar yang cocok adalah 5

Ha! Cobalah dengan paket regexp varietas taman Anda ...

Perhatikan bahwa variabel $z0 dan $z1 tidak diganti ketika regexp dikompilasi, sebagai
terjadi untuk variabel biasa di luar ekspresi kode. Sebaliknya, seluruh blok kode adalah
diuraikan sebagai kode perl pada saat yang sama dengan perl mengkompilasi kode yang berisi literal
pola regexp.

Regexp tanpa pengubah "//x" adalah

/^1(?:((??{ $z0 }))1(?{ $z0 = $z1; $z1 .= $^N; }))+$/

yang menunjukkan bahwa spasi masih dimungkinkan di bagian kode. Namun demikian, saat bekerja
dengan kode dan ekspresi kondisional, bentuk regexp yang diperluas hampir diperlukan dalam
membuat dan men-debug regexps.

Mundur kontrol kata kerja
Perl 5.10 memperkenalkan sejumlah kata kerja kontrol yang dimaksudkan untuk memberikan kontrol rinci atas
proses backtracking, dengan secara langsung mempengaruhi mesin regexp dan dengan menyediakan
teknik pemantauan. Karena semua fitur dalam grup ini bersifat eksperimental dan tunduk pada
perubahan atau penghapusan di versi Perl yang akan datang, pembaca yang tertarik dirujuk ke
"Kata Kerja Kontrol Backtracking Khusus" di perlre untuk penjelasan rinci.

Di bawah ini hanya satu contoh, yang menggambarkan kata kerja kontrol "(*GAGAL)", yang mungkin
disingkat "(*F)". Jika ini dimasukkan ke dalam regexp, itu akan menyebabkannya gagal, sama seperti
itu akan pada beberapa ketidakcocokan antara pola dan string. Pemrosesan regexp
berlanjut seperti setelah kegagalan "normal", sehingga, misalnya, posisi berikutnya
dalam string atau alternatif lain akan dicoba. Karena gagal mencocokkan tidak melestarikan
menangkap kelompok atau menghasilkan hasil, mungkin perlu menggunakan ini dalam kombinasi dengan
kode tertanam.

%hitung = ();
"supercalifragilisticexpialidocious" =~
/([aeiou])(?{ $hitung{$1}++; })(*GAGAL)/i;
printf "%3d '%s'\n", $count{$_}, $_ for (mengurutkan kunci %count);

Polanya dimulai dengan kelas yang cocok dengan subset huruf. Kapan pun ini cocok, a
pernyataan seperti "$count{'a'}++;" dieksekusi, menambah penghitung surat. Kemudian
"(*GAGAL)" melakukan apa yang dikatakannya, dan mesin regexp berjalan sesuai dengan buku: selama
karena ujung senar belum tercapai, posisinya dimajukan sebelum mencari
vokal lain. Jadi, cocok atau tidak cocok tidak ada bedanya, dan mesin regexp berjalan
sampai seluruh string telah diperiksa. (Sungguh luar biasa bahwa solusi alternatif
menggunakan sesuatu seperti

$count{lc($_)}++ untuk split('', "supercalifragilisticexpialidocious");
printf "%3d '%s'\n", $count2{$_}, $_ for ( qw{ aeiou } );

jauh lebih lambat.)

pragma dan debugging
Berbicara tentang debugging, ada beberapa pragma yang tersedia untuk mengontrol dan men-debug regexps di
Perl. Kita telah menemukan satu pragma di bagian sebelumnya, "use re 'eval';",
yang memungkinkan interpolasi variabel dan ekspresi kode untuk hidup berdampingan dalam regexp. Yang lain
pragma adalah

gunakan re 'noda';
$tercemar = <>;
@parts = ($tainted =~ /(\w+)\s+(\w+)/; # @parts sekarang tainted

Pragma "noda" menyebabkan substring apa pun dari kecocokan dengan variabel tercemar menjadi
tercemar juga. Ini biasanya tidak terjadi, karena regexps sering digunakan untuk mengekstrak
bit aman dari variabel tercemar. Gunakan "taint" saat Anda tidak mengekstrak bit yang aman, tapi
sedang melakukan beberapa pemrosesan lainnya. Baik pragma "noda" dan "eval" secara leksikal
scoped, yang berarti mereka hanya berlaku sampai akhir blok yang melampirkan
pragma.

gunakan '/m'; # atau bendera lainnya
$multiline_string =~ /^foo/; # /m tersirat

Pragma "re '/flags'" (diperkenalkan di Perl 5.14) mengaktifkan ekspresi reguler yang diberikan
bendera sampai akhir lingkup leksikal. Lihat "'/flags' mode" untuk detail lebih lanjut.

gunakan 'debug' ulang;
/^(.*)$/s; # keluaran info debug

gunakan kembali 'debugcolor';
/^(.*)$/s; # keluaran info debug dalam warna hidup

Pragma global "debug" dan "debugcolor" memungkinkan seseorang untuk mendapatkan info debug mendetail tentang
kompilasi dan eksekusi regexp. "debugcolor" sama dengan debug, kecuali debugging
informasi ditampilkan dalam warna pada terminal yang dapat menampilkan urutan warna termcap.
Berikut adalah contoh keluaran:

% perl -e 'gunakan kembali "debug"; "abc" =~ /a*b+c/;'
Kompilasi REx 'a*b+c'
ukuran 9 pertama pada 1
1: STAR(4)
2: PERSIS (0)
4: PLUS(7)
5: TEPAT (0)
7: TEPAT (9)
9: AKHIR(0)
mengambang 'bc' di 0..2147483647 (memeriksa mengambang) minlen 2
Menebak awal pertandingan, REx 'a*b+c' melawan 'abc'...
Ditemukan substr 'bc' mengambang di offset 1...
Ditebak: cocok di offset 0
Mencocokkan REx 'a*b+c' dengan 'abc'
Mengatur ruang lingkup EVAL, savestack = 3
0 <> | 1: BINTANG
EXACT dapat mencocokkan 1 kali dari 32767...
Mengatur ruang lingkup EVAL, savestack = 3
1 | 4: PLUS
EXACT dapat mencocokkan 1 kali dari 32767...
Mengatur ruang lingkup EVAL, savestack = 3
2 | 7: TEPAT
3 <> | 9: SELESAI
Pertandingan berhasil!
Membebaskan REx: 'a*b+c'

Jika Anda sudah sampai sejauh ini dalam tutorial, Anda mungkin bisa menebak apa bedanya
bagian dari output debugging memberitahu Anda. Bagian pertama

Kompilasi REx 'a*b+c'
ukuran 9 pertama pada 1
1: STAR(4)
2: PERSIS (0)
4: PLUS(7)
5: TEPAT (0)
7: TEPAT (9)
9: AKHIR(0)

menjelaskan tahap kompilasi. STAR(4) berarti ada objek yang berbintang, dalam hal ini
huruf 'a', dan jika cocok, buka baris 4, yaitu, PLUS(7). Garis tengah menggambarkan beberapa
heuristik dan optimasi yang dilakukan sebelum pertandingan:

mengambang 'bc' di 0..2147483647 (memeriksa mengambang) minlen 2
Menebak awal pertandingan, REx 'a*b+c' melawan 'abc'...
Ditemukan substr 'bc' mengambang di offset 1...
Ditebak: cocok di offset 0

Kemudian kecocokan dijalankan dan baris yang tersisa menjelaskan prosesnya:

Mencocokkan REx 'a*b+c' dengan 'abc'
Mengatur ruang lingkup EVAL, savestack = 3
0 <> | 1: BINTANG
EXACT dapat mencocokkan 1 kali dari 32767...
Mengatur ruang lingkup EVAL, savestack = 3
1 | 4: PLUS
EXACT dapat mencocokkan 1 kali dari 32767...
Mengatur ruang lingkup EVAL, savestack = 3
2 | 7: TEPAT
3 <> | 9: SELESAI
Pertandingan berhasil!
Membebaskan REx: 'a*b+c'

Setiap langkah berbentuk "n ", dengan " " bagian dari string cocok dan " "
bagian belum cocok. "| 1: STAR" mengatakan bahwa Perl ada di baris nomor 1 di
daftar kompilasi di atas. Lihat "Men-debug Ekspresi Reguler" di perldebguts untuk lebih banyak lagi
detail.

Metode alternatif untuk men-debug regexps adalah dengan menyematkan pernyataan "cetak" di dalam
reg. Ini memberikan akun pukulan demi pukulan dari backtracking secara bergantian:

"bahwa ini" =~ m@(?{print "Mulai dari posisi ", pos, "\n";})
t(?{cetak "t1\n";})
h(?{cetak "h1\n";})
i(?{cetak "i1\n";})
s(?{cetak "s1\n";})
|
t(?{cetak "t2\n";})
h(?{cetak "h2\n";})
a(?{cetak "a2\n";})
t(?{cetak "t2\n";})
(?{cetak "Selesai di posisi ", pos, "\n";})
@X;

cetakan

Mulai dari posisi 0
t1
h1
t2
h2
a2
t2
Selesai di posisi 4

Gunakan perlretut online menggunakan layanan onworks.net


Server & Workstation Gratis

Unduh aplikasi Windows & Linux

Perintah Linux

Ad