
Apakah ungkapan biasa (regex)?
Malah, ungkapan biasa ialah corak untuk mencari rentetan dalam teks. Di Jawa, perwakilan asal corak ini sentiasa rentetan, iaitu objek kelasString
. Walau bagaimanapun, ia bukan sebarang rentetan yang boleh disusun menjadi ungkapan biasa — hanya rentetan yang mematuhi peraturan untuk mencipta ungkapan biasa. Sintaks ditakrifkan dalam spesifikasi bahasa. Ungkapan biasa ditulis menggunakan huruf dan nombor, serta metacharacters, iaitu aksara yang mempunyai makna istimewa dalam sintaks ungkapan biasa. Sebagai contoh:
String regex = "java"; // The pattern is "java";
String regex = "\\d{3}"; // The pattern is three digits;
Mencipta ungkapan biasa dalam Java
Mencipta ungkapan biasa dalam Java melibatkan dua langkah mudah:- tuliskannya sebagai rentetan yang mematuhi sintaks ungkapan biasa;
- menyusun rentetan menjadi ungkapan biasa;
Pattern
objek. Untuk melakukan ini, kita perlu memanggil salah satu daripada dua kaedah statik kelas: compile
. Kaedah pertama mengambil satu hujah — rentetan literal yang mengandungi ungkapan biasa, manakala kaedah kedua mengambil hujah tambahan yang menentukan tetapan padanan corak:
public static Pattern compile (String literal)
public static Pattern compile (String literal, int flags)
Senarai nilai potensi parameter flags
ditakrifkan dalam Pattern
kelas dan tersedia kepada kami sebagai pembolehubah kelas statik. Sebagai contoh:
Pattern pattern = Pattern.compile("java", Pattern.CASE_INSENSITIVE); // Pattern-matching will be case insensitive.
Pada asasnya, Pattern
kelas adalah pembina untuk ungkapan biasa. Di bawah tudung, compile
kaedah memanggil Pattern
pembina peribadi kelas untuk mencipta perwakilan yang disusun. Mekanisme penciptaan objek ini dilaksanakan dengan cara ini untuk mencipta objek tidak berubah. Apabila ungkapan biasa dibuat, sintaksnya diperiksa. Jika rentetan mengandungi ralat, maka a PatternSyntaxException
dijana.
Sintaks ungkapan biasa
Sintaks ungkapan biasa bergantung pada<([{\^-=$!|]})?*+.>
aksara, yang boleh digabungkan dengan huruf. Bergantung kepada peranan mereka, mereka boleh dibahagikan kepada beberapa kumpulan:
Metacharacter | Penerangan |
---|---|
^ | permulaan baris |
$ | hujung baris |
\b | sempadan perkataan |
\B | sempadan bukan perkataan |
\A | permulaan input |
\G | tamat perlawanan sebelumnya |
\Z | akhir input |
\z | akhir input |
Metacharacter | Penerangan |
---|---|
\d | digit |
\D | bukan digit |
\s | watak ruang putih |
\S | aksara bukan ruang putih |
\w | aksara abjad angka atau garis bawah |
\W | sebarang aksara kecuali huruf, nombor dan garis bawah |
. | sebarang watak |
Metacharacter | Penerangan |
---|---|
\t | watak tab |
\n | watak baris baharu |
\r | pemulangan pengangkutan |
\f | watak suapan baris |
\u0085 | watak baris seterusnya |
\u2028 | pemisah garis |
\u2029 | pemisah perenggan |
Metacharacter | Penerangan |
---|---|
[abc] | mana-mana aksara yang disenaraikan (a, b, atau c) |
[^abc] | sebarang aksara selain daripada yang disenaraikan (bukan a, b, atau c) |
[a-zA-Z] | julat digabungkan (aksara Latin dari a hingga z, tidak peka huruf besar-besaran) |
[iklan[mp]] | penyatuan aksara (dari a ke d dan dari m ke p) |
[az&&[def]] | persilangan aksara (d, e, f) |
[az&&[^bc]] | penolakan aksara (a, dz) |
Metacharacter | Penerangan |
---|---|
? | satu atau tiada |
* | sifar atau lebih kali |
+ | satu kali atau lebih |
{n} | n kali |
{n,} | n atau lebih kali |
{n,m} | sekurang-kurangnya n kali dan tidak lebih daripada m kali |
Pengkuantiti yang tamak
Satu perkara yang perlu anda ketahui tentang pengkuantiti ialah ia datang dalam tiga jenis berbeza: tamak, posesif dan enggan. Anda membuat pengkuantiti posesif dengan menambahkan+
aksara " " selepas pengkuantiti. Anda membuatnya keberatan dengan menambah " ?
". Sebagai contoh:
"A.+a" // greedy
"A.++a" // possessive
"A.+?a" // reluctant
Mari cuba gunakan corak ini untuk memahami cara pelbagai jenis pengkuantiti berfungsi. Secara lalai, pengkuantiti adalah tamak. Ini bermakna mereka mencari perlawanan terpanjang dalam rentetan. Jika kita menjalankan kod berikut:
public static void main(String[] args) {
String text = "Fred Anna Alexander";
Pattern pattern = Pattern.compile("A.+a");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(text.substring(matcher.start(), matcher.end()));
}
}
kami mendapat output ini:
Anna Alexa
Untuk ungkapan biasa " A.+a
", padanan corak dilakukan seperti berikut:
-
Aksara pertama dalam corak yang ditentukan ialah huruf Latin
A
.Matcher
membandingkannya dengan setiap aksara teks, bermula dari sifar indeks. WatakF
berada pada indeks sifar dalam teks kami, jadiMatcher
berulang melalui aksara sehingga ia sepadan dengan corak. Dalam contoh kami, watak ini terdapat pada indeks 5. -
Setelah padanan dengan watak pertama corak ditemui,
Matcher
cari padanan dengan watak kedua. Dalam kes kami, ia ialah.
watak " ", yang bermaksud mana-mana watak.Watak itu
n
berada di kedudukan keenam. Ia sudah tentu layak sebagai perlawanan untuk "sebarang watak". -
Matcher
terus menyemak watak corak seterusnya. Dalam corak kami, ia termasuk dalam pengkuantiti yang digunakan pada aksara sebelumnya: ".+
". Oleh kerana bilangan ulangan "mana-mana aksara" dalam corak kami adalah satu atau lebih kali,Matcher
berulang kali mengambil aksara seterusnya daripada rentetan dan menyemaknya terhadap corak selagi ia sepadan dengan "mana-mana watak". Dalam contoh kami — sehingga akhir rentetan (dari indeks 7 hingga indeks 18).Pada asasnya,
Matcher
melahap rentetan hingga akhir — inilah yang dimaksudkan dengan "tamak". -
Selepas Matcher mencapai penghujung teks dan menyelesaikan semakan untuk
A.+
bahagian " " corak, ia mula menyemak corak yang lain:a
. Tiada lagi teks ke hadapan, jadi semakan diteruskan dengan "undur", bermula dari aksara terakhir: -
Matcher
"mengingat" bilangan ulangan dalam.+
bahagian " " corak. Pada ketika ini, ia mengurangkan bilangan ulangan sebanyak satu dan menyemak corak yang lebih besar terhadap teks sehingga padanan ditemui:
Pengkuantiti posesif
Pengkuantiti posesif adalah sama seperti yang tamak. Perbezaannya ialah apabila teks telah ditangkap ke penghujung rentetan, tiada padanan corak semasa "undur". Dalam erti kata lain, tiga peringkat pertama adalah sama seperti pengkuantiti tamak. Selepas menangkap keseluruhan rentetan, pemadan menambahkan selebihnya corak pada apa yang sedang dipertimbangkan dan membandingkannya dengan rentetan yang ditangkap. Dalam contoh kami, menggunakan ungkapan biasa "A.++a
", kaedah utama tidak menemui padanan. 
Pengkuantiti enggan
-
Untuk pengkuantiti ini, seperti varieti tamak, kod mencari padanan berdasarkan aksara pertama corak:
-
Kemudian ia mencari padanan dengan watak seterusnya corak (sebarang watak):
-
Tidak seperti padanan corak tamak, padanan terpendek dicari dalam padanan corak enggan. Ini bermakna bahawa selepas mencari padanan dengan aksara kedua corak (titik, yang sepadan dengan aksara pada kedudukan 6 dalam teks,
Matcher
menyemak sama ada teks sepadan dengan corak yang lain — aksara "a
" -
Teks tidak sepadan dengan corak (iaitu ia mengandungi aksara "
n
" pada indeks 7), jadiMatcher
menambah satu "mana-mana aksara", kerana pengkuantiti menunjukkan satu atau lebih. Kemudian ia sekali lagi membandingkan corak dengan teks dalam kedudukan 5 hingga 8:
Dalam kes kami, padanan ditemui, tetapi kami belum sampai ke penghujung teks lagi. Oleh itu, padanan corak dimulakan semula dari kedudukan 9, iaitu aksara pertama corak dicari menggunakan algoritma yang serupa dan ini berulang sehingga akhir teks.

main
kaedah memperoleh hasil berikut apabila menggunakan corak " A.+?a
": Anna Alexa Seperti yang anda boleh lihat daripada contoh kami, jenis pengkuantiti yang berbeza menghasilkan keputusan yang berbeza untuk corak yang sama. Oleh itu, ingatlah perkara ini dan pilih varieti yang betul berdasarkan perkara yang anda cari.
Melarikan diri aksara dalam ungkapan biasa
Oleh kerana ungkapan biasa dalam Java, atau lebih tepatnya, perwakilan asalnya, ialah literal rentetan, kita perlu mengambil kira peraturan Java berkenaan literal rentetan. Khususnya, aksara backslash "\
" dalam literal rentetan dalam kod sumber Java ditafsirkan sebagai watak kawalan yang memberitahu pengkompil bahawa aksara seterusnya adalah istimewa dan mesti ditafsirkan dengan cara yang istimewa. Sebagai contoh:
String s = "The root directory is \nWindows"; // Move "Windows" to a new line
String s = "The root directory is \u00A7Windows"; // Insert a paragraph symbol before "Windows"
Ini bermakna literal rentetan yang menerangkan ungkapan biasa dan menggunakan \
aksara " " (iaitu untuk menunjukkan aksara meta) mesti mengulang garis miring ke belakang untuk memastikan pengkompil kod bait Java tidak menyalahtafsir rentetan. Sebagai contoh:
String regex = "\\s"; // Pattern for matching a whitespace character
String regex = "\"Windows\""; // Pattern for matching "Windows"
Garis miring ke belakang berganda juga mesti digunakan untuk melepaskan aksara khas yang kita mahu gunakan sebagai aksara "biasa". Sebagai contoh:
String regex = "How\\?"; // Pattern for matching "How?"
Kaedah kelas Corak
KelasPattern
mempunyai kaedah lain untuk bekerja dengan ungkapan biasa:
-
String pattern()
‒ mengembalikan perwakilan rentetan asal ungkapan biasa yang digunakan untuk menciptaPattern
objek:Pattern pattern = Pattern.compile("abc"); System.out.println(pattern.pattern()); // "abc"
-
static boolean matches(String regex, CharSequence input)
– membolehkan anda menyemak ungkapan biasa yang diluluskan sebagai regex terhadap teks yang diluluskan sebagaiinput
. Pulangan:benar – jika teks sepadan dengan corak;
palsu – jika tidak;Sebagai contoh:
System.out.println(Pattern.matches("A.+a","Anna")); // true System.out.println(Pattern.matches("A.+a","Fred Anna Alexander")); // false
-
int flags()
‒ mengembalikan nilaiflags
set parameter corak apabila corak dicipta atau 0 jika parameter tidak ditetapkan. Sebagai contoh:Pattern pattern = Pattern.compile("abc"); System.out.println(pattern.flags()); // 0 Pattern pattern = Pattern.compile("abc",Pattern.CASE_INSENSITIVE); System.out.println(pattern.flags()); // 2
-
String[] split(CharSequence text, int limit)
– membahagikan teks yang diluluskan kepadaString
tatasusunan. Parameterlimit
menunjukkan bilangan maksimum padanan yang dicari dalam teks:- jika
limit > 0
‒limit-1
sepadan; - jika
limit < 0
‒ semua sepadan dalam teks - jika
limit = 0
‒ semua padanan dalam teks, rentetan kosong pada penghujung tatasusunan akan dibuang;
Sebagai contoh:
public static void main(String[] args) { String text = "Fred Anna Alexa"; Pattern pattern = Pattern.compile("\\s"); String[] strings = pattern.split(text,2); for (String s : strings) { System.out.println(s); } System.out.println("---------"); String[] strings1 = pattern.split(text); for (String s : strings1) { System.out.println(s); } }
Output konsol:
Fred Anna Alexa --------- Fred Anna Alexa
Di bawah ini kita akan mempertimbangkan satu lagi kaedah kelas yang digunakan untuk mencipta
Matcher
objek. - jika
Kaedah kelas Matcher
Kejadian kelasMatcher
dibuat untuk melakukan padanan corak. Matcher
ialah "enjin carian" untuk ungkapan biasa. Untuk melakukan carian, kita perlu memberikannya dua perkara: corak dan indeks permulaan. Untuk mencipta Matcher
objek, Pattern
kelas menyediakan kaedah berikut: рublic Matcher matcher(CharSequence input)
Kaedah mengambil urutan aksara, yang akan dicari. Ini ialah contoh kelas yang melaksanakan CharSequence
antara muka. Anda boleh lulus bukan sahaja a String
, tetapi juga a StringBuffer
, StringBuilder
, Segment
, atau CharBuffer
. Corak adalah Pattern
objek di mana matcher
kaedah dipanggil. Contoh membuat padanan:
Pattern p = Pattern.compile("a*b"); // Create a compiled representation of the regular expression
Matcher m = p.matcher("aaaaab"); // Create a "search engine" to search the text "aaaaab" for the pattern "a*b"
Kini kami boleh menggunakan "enjin carian" kami untuk mencari padanan, mendapatkan kedudukan padanan dalam teks dan menggantikan teks menggunakan kaedah kelas. Kaedah boolean find()
mencari padanan seterusnya dalam teks. Kita boleh menggunakan kaedah ini dan pernyataan gelung untuk menganalisis keseluruhan teks sebagai sebahagian daripada model peristiwa. Dalam erti kata lain, kita boleh melakukan operasi yang diperlukan apabila sesuatu peristiwa berlaku, iaitu apabila kita menemui padanan dalam teks. Sebagai contoh, kita boleh menggunakan kelas int start()
dan int end()
kaedah ini untuk menentukan kedudukan padanan dalam teks. Dan kita boleh menggunakan kaedah String replaceFirst(String replacement)
dan String replaceAll(String replacement)
untuk menggantikan padanan dengan nilai parameter penggantian. Sebagai contoh:
public static void main(String[] args) {
String text = "Fred Anna Alexa";
Pattern pattern = Pattern.compile("A.+?a");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
int start=matcher.start();
int end=matcher.end();
System.out.println("Match found: " + text.substring(start, end) + " from index "+ start + " through " + (end-1));
}
System.out.println(matcher.replaceFirst("Ira"));
System.out.println(matcher.replaceAll("Mary"));
System.out.println(text);
}
Pengeluaran:
Match found: Anna from index 5 through 8
Match found: Alexa from index 10 through 14
Fred Ira Alexa
Fred Mary Mary
Fred Anna Alexa
Contoh menjelaskan bahawa kaedah replaceFirst
dan replaceAll
mencipta String
objek baharu — rentetan di mana corak padanan dalam teks asal digantikan dengan teks yang dihantar kepada kaedah sebagai hujah. Selain itu, replaceFirst
kaedah menggantikan hanya padanan pertama, tetapi replaceAll
kaedah menggantikan semua padanan dalam teks. Teks asal kekal tidak berubah. Operasi regex yang paling kerap Pattern
dan Matcher
kelas dibina terus ke dalam String
kelas. Ini adalah kaedah seperti split
, matches
, replaceFirst
dan replaceAll
. Tetapi di bawah tudung, kaedah ini menggunakan Pattern
dan Matcher
kelas. Jadi jika anda ingin menggantikan teks atau membandingkan rentetan dalam atur cara tanpa menulis sebarang kod tambahan, gunakan kaedahString
kelas. Jika anda memerlukan ciri yang lebih maju, ingat Pattern
dan Matcher
kelas.
Kesimpulan
Dalam program Java, ungkapan biasa ditakrifkan oleh rentetan yang mematuhi peraturan padanan corak tertentu. Apabila melaksanakan kod, mesin Java menyusun rentetan ini ke dalamPattern
objek dan menggunakan Matcher
objek untuk mencari padanan dalam teks. Seperti yang saya katakan pada mulanya, orang sering menangguhkan ungkapan biasa untuk kemudian, menganggapnya sebagai topik yang sukar. Tetapi jika anda memahami sintaks asas, aksara meta, dan pelarian aksara, dan mengkaji contoh ungkapan biasa, maka anda akan mendapati ia lebih mudah daripada yang dipaparkan pada pandangan pertama.
Bacaan lanjut: |
---|
GO TO FULL VERSION