JavaRush /Blog Java /Random-MS /Ungkapan Biasa dalam Java (RegEx)

Ungkapan Biasa dalam Java (RegEx)

Diterbitkan dalam kumpulan
Ungkapan biasa ialah topik yang pengaturcara, malah yang berpengalaman, sering menangguhkan sehingga kemudian. Walau bagaimanapun, kebanyakan pembangun Java lambat laun perlu berurusan dengan pemprosesan teks. Selalunya - dengan operasi carian dalam teks dan penyuntingan. Tanpa ungkapan biasa, kod program yang produktif dan padat yang dikaitkan dengan pemprosesan teks tidak dapat difikirkan. Oleh itu, berhenti menangguhkannya, mari kita berurusan dengan "orang biasa" sekarang. Ini bukan tugas yang sukar.

Apakah ungkapan biasa RegEx?

Malah, ungkapan biasa (RegEx dalam Java) ialah corak untuk mencari rentetan dalam teks. Di Jawa, perwakilan awal corak ini sentiasa rentetan, iaitu, objek kelas String. Walau bagaimanapun, tiada sebarang rentetan boleh disusun menjadi ungkapan biasa, hanya rentetan yang mengikut peraturan untuk menulis ungkapan biasa - sintaks yang ditakrifkan dalam spesifikasi bahasa. Untuk menulis ungkapan biasa, aksara abjad dan angka digunakan, serta aksara meta - aksara yang mempunyai makna istimewa dalam sintaks ungkapan biasa. Sebagai contoh:
String regex = "java"; // string template "java";
String regex = "\\d{3}"; // string template of three numeric characters;

Mencipta Ungkapan Biasa di Jawa

Untuk membuat RegEx di Java, anda perlu mengikuti dua langkah mudah:
  1. tuliskannya sebagai rentetan menggunakan sintaks ungkapan biasa;
  2. susun rentetan ini menjadi ungkapan biasa;
Bekerja dengan ungkapan biasa dalam mana-mana program Java bermula dengan mencipta objek kelas Pattern. Untuk melakukan ini, anda perlu memanggil salah satu daripada dua kaedah statik yang tersedia dalam kelas compile. Kaedah pertama mengambil satu hujah - rentetan literal ungkapan biasa, dan yang kedua - ditambah parameter lain yang menghidupkan mod untuk membandingkan templat dengan teks:
public static Pattern compile (String literal)
public static Pattern compile (String literal, int flags)
Senarai nilai parameter yang mungkin flagsditakrifkan dalam kelas Patterndan tersedia untuk kami sebagai pembolehubah kelas statik. Sebagai contoh:
Pattern pattern = Pattern.compile("java", Pattern.CASE_INSENSITIVE);//searching for matches with the pattern will be done case-insensitively.
Pada asasnya, kelas Patternialah pembina ungkapan biasa. Di bawah tudung, kaedah compilememanggil pembina peribadi kelas Patternuntuk membuat paparan tersusun. Kaedah mencipta contoh templat ini dilaksanakan dengan matlamat untuk menciptanya sebagai objek tidak berubah. Semasa membuat, semakan sintaks bagi ungkapan biasa dilakukan. Jika terdapat ralat dalam baris, pengecualian dijana PatternSyntaxException.

Sintaks ungkapan biasa

Sintaks ungkapan biasa adalah berdasarkan penggunaan simbol <([{\^-=$!|]})?*+.>, yang boleh digabungkan dengan aksara abjad. Bergantung kepada peranan mereka, mereka boleh dibahagikan kepada beberapa kumpulan:
1. Metacharacter untuk memadankan sempadan garisan atau teks
Metacharacter Tujuan
^ permulaan baris
$ hujung baris
\b sempadan perkataan
\B bukan had perkataan
\A permulaan input
\G tamat perlawanan sebelumnya
\Z akhir input
\z akhir input
2. Metacharacters untuk mencari kelas watak
Metacharacter Tujuan
\d simbol digital
\D aksara bukan angka
\s watak angkasa
\S aksara bukan ruang putih
\w aksara abjad angka atau garis bawah
\W sebarang aksara selain daripada abjad, angka atau garis bawah
. sebarang watak
3. Metacharacter untuk mencari simbol penyuntingan teks
Metacharacter Tujuan
\t watak tab
\n watak baris baharu
\r watak pemulangan kereta
\f pergi ke halaman baharu
\u0085 watak baris seterusnya
\u 2028 watak pemisah baris
\u 2029 simbol pemisah perenggan
4. Metacharacter untuk mengumpulkan watak
Metacharacter Tujuan
[a B C] mana-mana di atas (a, b, atau c)
[^abc] mana-mana selain daripada yang disenaraikan (bukan a, b, c)
[a-zA-Z] penggabungan julat (aksara Latin a hingga z tidak peka huruf besar-besaran)
[iklan[mp]] penyatuan aksara (a hingga d dan m hingga p)
[az&&[def]] persilangan simbol (simbol d,e,f)
[az&&[^bc]] tolak aksara (aksara a, dz)
5. Metasimbol untuk menunjukkan bilangan aksara - pengkuantiti. Pengkuantiti sentiasa datang selepas watak atau kumpulan aksara.
Metacharacter Tujuan
? satu atau tidak hadir
* sifar atau lebih kali
+ satu kali atau lebih
{n} n kali
{n,} n kali atau lebih
{n,m} tidak kurang daripada n kali dan tidak lebih daripada m kali

Mod pengkuantiti tamak

Ciri khas pengkuantiti ialah keupayaan untuk menggunakannya dalam mod yang berbeza: tamak, sangat tamak dan malas. Mod lebih tamak dihidupkan dengan menambahkan simbol “ +” selepas pengkuantiti, dan mod malas dengan menambahkan simbol “ ?“. Sebagai contoh:
"A.+a" // greedy mode
"A.++a" // over-greedy mode
"A.+?a" // lazy mode
Menggunakan templat ini sebagai contoh, mari cuba memahami cara pengkuantiti berfungsi dalam mod yang berbeza. Secara lalai, pengkuantiti beroperasi dalam mod tamak. Ini bermakna ia mencari padanan terpanjang yang mungkin dalam rentetan. Hasil daripada menjalankan kod ini:
public static void main(String[] args) {
    String text = "Egor Alla Alexander";
    Pattern pattern = Pattern.compile("A.+a");
    Matcher matcher = pattern.matcher(text);
    while (matcher.find()) {
        System.out.println(text.substring(matcher.start(), matcher.end()));
    }
}
kita akan mendapat output berikut: Alla Alexa Algoritma carian untuk corak tertentu " А.+а" dilakukan dalam urutan berikut:
  1. Dalam corak yang diberikan, aksara pertama ialah aksara huruf Rusia А. Matchermemadankannya dengan setiap aksara teks, bermula pada kedudukan sifar. Pada kedudukan sifar dalam teks kita terdapat simbol Е, jadi Matcheria melalui aksara dalam teks secara berurutan sehingga ia memenuhi padanan dengan corak. Dalam contoh kami, ini adalah simbol pada kedudukan No. 5.

    Ungkapan Biasa dalam Java - 2
  2. Selepas padanan ditemui dengan aksara pertama corak, Matcheria menyemak padanan dengan aksara kedua corak. Dalam kes kami, ini ialah simbol " .", yang bermaksud mana-mana watak.

    Ungkapan Biasa dalam Java - 3

    Di kedudukan keenam ialah simbol huruf л. Sudah tentu, ia sepadan dengan corak "sebarang watak".

  3. Matcherberalih kepada menyemak aksara seterusnya daripada corak. Dalam templat kami, ia ditentukan menggunakan .+pengkuantiti " ". Oleh kerana bilangan ulangan "mana-mana watak" dalam corak adalah satu atau lebih kali, Matcheria mengambil aksara seterusnya daripada rentetan secara bergilir-gilir dan menyemaknya untuk pematuhan dengan corak, selagi syarat "mana-mana watak" dipenuhi, dalam contoh kami - sehingga akhir baris ( dari kedudukan No. 7 - No. 18 teks).

    Ungkapan Biasa dalam Java - 4

    Malah, Matcheria menangkap keseluruhan baris hingga akhir - di sinilah "keserakahan"nya menjelma.

  4. Selepas Matchersampai ke penghujung teks dan selesai menyemak А.+bahagian “ ” corak, Matcher mula menyemak corak yang lain - aksara huruf а. Memandangkan teks dalam arah hadapan telah tamat, semakan berlaku dalam arah songsang, bermula dari aksara terakhir:

    Ungkapan Biasa dalam Java - 5
  5. Matcher"mengingat" bilangan ulangan dalam corak " .+" di mana ia mencapai penghujung teks, jadi ia mengurangkan bilangan ulangan sebanyak satu dan menyemak corak untuk teks sehingga padanan ditemui: Ungkapan Biasa dalam Java - 6

Mod pengkuantiti sangat tamak

Dalam mod super tamak, pemadan berfungsi sama dengan mekanisme mod tamak. Perbezaannya ialah apabila anda mengambil teks ke hujung baris, tiada carian ke belakang. Iaitu, tiga peringkat pertama dalam mod super tamak akan serupa dengan mod tamak. Selepas menangkap keseluruhan rentetan, pemadan menambah corak yang lain dan membandingkannya dengan rentetan yang ditangkap. Dalam contoh kami, apabila melaksanakan kaedah utama dengan corak " А.++а", tiada padanan akan ditemui. Ungkapan Biasa dalam Java - 7

Mod pengkuantiti malas

  1. Dalam mod ini, pada peringkat awal, seperti dalam mod tamak, padanan dicari dengan watak pertama corak:

    Ungkapan Biasa dalam Java - 8
  2. Seterusnya, ia mencari padanan dengan watak seterusnya dalam corak - mana-mana watak:

    Ungkapan Biasa dalam Java - 9
  3. Tidak seperti mod tamak, mod malas mencari padanan terpendek dalam teks, jadi selepas mencari padanan dengan aksara kedua corak, yang ditentukan oleh titik dan sepadan dengan watak pada kedudukan No. 6 teks, ia Matcherakan menyemak sama ada teks sepadan dengan corak yang lain - aksara “ а” .

    Ungkapan Biasa dalam Java - 10
  4. Memandangkan padanan dengan corak dalam teks tidak ditemui (pada kedudukan No. 7 dalam teks terdapat simbol “ л“), Matcheria menambah satu lagi “mana-mana aksara” dalam corak, kerana ia dinyatakan sebagai satu atau lebih kali, dan sekali lagi membandingkan corak dengan teks pada kedudukan dengan No. 5 hingga No. 8:

    Ungkapan Biasa dalam Java - 11
  5. Dalam kes kami, perlawanan ditemui, tetapi penghujung teks masih belum dicapai. Oleh itu, dari kedudukan No. 9, semakan bermula dengan mencari aksara pertama corak menggunakan algoritma yang serupa dan kemudian berulang sehingga akhir teks.

    Ungkapan Biasa dalam Java - 12
Hasil daripada kaedah tersebut, mainapabila menggunakan templat " А.+?а", kami akan mendapat hasil berikut: Alla Alexa Seperti yang dapat dilihat daripada contoh kami, apabila menggunakan mod pengkuantiti yang berbeza untuk templat yang sama, kami mendapat hasil yang berbeza. Oleh itu, adalah perlu untuk mengambil kira ciri ini dan pilih mod yang dikehendaki bergantung pada hasil yang dikehendaki semasa carian.

Melarikan diri aksara dalam ungkapan biasa

Oleh kerana ungkapan biasa dalam Java, atau lebih tepat lagi perwakilan awalnya, ditentukan menggunakan literal rentetan, adalah perlu untuk mengambil kira peraturan spesifikasi Java yang berkaitan dengan literal rentetan. Khususnya, aksara garisan belakang " \" dalam literal rentetan dalam kod sumber Java ditafsirkan sebagai aksara melarikan diri yang memberi amaran kepada pengkompil bahawa aksara yang mengikutinya ialah aksara khas dan mesti ditafsirkan dengan cara yang istimewa. Sebagai contoh:
String s = "The root directory is \nWindows";//wrap Windows to a new line
String s = "The root directory is \u00A7Windows";//insert paragraph character before Windows
Oleh itu, dalam literal rentetan yang menerangkan ungkapan biasa dan menggunakan \aksara " " (contohnya, untuk aksara meta), ia mesti digandakan supaya pengkompil bytecode Java tidak mentafsirkannya secara berbeza. Sebagai contoh:
String regex = "\\s"; // template for searching for space characters
String regex = "\"Windows\""; // pattern to search for the string "Windows"
Aksara sengkang ke belakang berganda juga harus digunakan untuk melepaskan aksara khas jika kita merancang untuk menggunakannya sebagai aksara "biasa". Sebagai contoh:
String regex = "How\\?"; // template for searching the string "How?"

Kaedah kelas Corak

Kelas Patternmempunyai kaedah lain untuk bekerja dengan ungkapan biasa: String pattern()– mengembalikan perwakilan rentetan asal bagi ungkapan biasa dari mana objek itu dicipta Pattern:
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 dalam parameter regex terhadap teks yang diluluskan dalam parameter input. Pulangan: benar – jika teks sepadan dengan corak; palsu – jika tidak; Contoh:
System.out.println(Pattern.matches("A.+a","Alla"));//true
System.out.println(Pattern.matches("A.+a","Egor Alla Alexander"));//false
int flags()– mengembalikan flagsnilai parameter templat yang telah ditetapkan semasa ia dibuat, atau 0 jika parameter ini tidak ditetapkan. 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 sebagai parameter kepada tatasusunan elemen String. Parameter limitmenentukan bilangan maksimum padanan yang dicari dalam teks:
  • bila limit>0– carian untuk limit-1perlawanan dilakukan;
  • di limit<0– mencari semua padanan dalam teks
  • bila limit=0– mencari semua padanan dalam teks, manakala baris kosong di hujung tatasusunan dibuang;
Contoh:
public static void main(String[] args) {
    String text = "Egor Alla Anna";
    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: Egor Alla Anna -------- Egor Alla Anna Kami akan mempertimbangkan kaedah kelas lain untuk mencipta objek Matcherdi bawah.

Kaedah kelas matcher

Matcherialah kelas dari mana objek dicipta untuk mencari corak. Matcher– ini ialah "enjin carian", "enjin" ungkapan biasa. Untuk mencari, dia perlu diberikan dua perkara: corak carian dan "alamat" untuk mencari. Untuk mencipta objek, Matcherkaedah berikut disediakan dalam kelas Pattern: рublic Matcher matcher(CharSequence input) Sebagai hujah, kaedah mengambil urutan aksara di mana carian akan dilakukan. Ini adalah objek kelas yang melaksanakan antara muka CharSequence. StringAnda boleh lulus bukan sahaja , tetapi juga ,, StringBufferdan StringBuildersebagai hujah . Templat carian ialah objek kelas di mana kaedah dipanggil . Contoh membuat padanan: SegmentCharBufferPatternmatcher
Pattern p = Pattern.compile("a*b");// compiled the regular expression into a view
Matcher m = p.matcher("aaaaab");//created a search engine in the text “aaaaab” using the pattern "a*b"
Kini, dengan bantuan "enjin carian" kami, kami boleh mencari padanan, mengetahui kedudukan padanan dalam teks dan menggantikan teks menggunakan kaedah kelas. Kaedah boolean find()mencari padanan seterusnya dalam teks dengan corak. Menggunakan kaedah ini dan pengendali gelung, anda boleh menganalisis keseluruhan teks mengikut model acara (menjalankan operasi yang diperlukan apabila peristiwa berlaku - mencari padanan dalam teks). Contohnya, menggunakan kaedah kelas ini, int start()anda int end()boleh menentukan kedudukan padanan dalam teks dan menggunakan kaedah String replaceFirst(String replacement), String replaceAll(String replacement)gantikan padanan dalam teks dengan teks gantian yang lain. Contoh:
public static void main(String[] args) {
    String text = "Egor Alla Anna";
    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) + " с "+ start + " By " + (end-1) + "position");
    }
    System.out.println(matcher.replaceFirst("Ira"));
    System.out.println(matcher.replaceAll("Olga"));
    System.out.println(text);
}
Output program: Padanan ditemui Alla dari 5 hingga 8 kedudukan Satu perlawanan ditemui Anna dari 10 hingga 13 kedudukan Egor Ira Anna Egor Olga Olga Egor Alla Anna Daripada contoh itu jelas bahawa kaedah replaceFirstmencipta replaceAllobjek baru String- rentetan, yang ialah teks sumber yang padanan dengan templat digantikan dengan teks yang dihantar kepada kaedah sebagai hujah. Selain itu, kaedah ini replaceFirsthanya menggantikan perlawanan pertama, dan replaceAllsemua perlawanan dalam ujian. Teks asal kekal tidak berubah. Penggunaan kaedah kelas lain Matcher, serta contoh ungkapan biasa, boleh didapati dalam siri artikel ini . Operasi yang paling biasa dengan ungkapan biasa apabila bekerja dengan teks adalah daripada kelas Patterndan Matcherdibina ke dalam String. Ini adalah kaedah seperti split, matches, replaceFirst, replaceAll. Tetapi sebenarnya, "di bawah tudung" mereka menggunakan Patterndan Matcher. Oleh itu, jika anda perlu menggantikan teks atau membandingkan rentetan dalam program tanpa menulis kod yang tidak perlu, gunakan kaedah String. Jika anda memerlukan keupayaan lanjutan, fikirkan tentang kelas Patterndan Matcher.

Kesimpulan

Ungkapan biasa diterangkan dalam program Java menggunakan rentetan yang sepadan dengan corak yang ditakrifkan oleh peraturan. Apabila kod berjalan, Java menyusun semula rentetan ini ke dalam objek kelas Patterndan menggunakan objek kelas Matcheruntuk mencari padanan dalam teks. Seperti yang saya katakan pada mulanya, ungkapan biasa sering diketepikan untuk kemudian, dianggap sebagai topik yang sukar. Walau bagaimanapun, jika anda memahami asas sintaks, aksara meta, melarikan diri dan mengkaji contoh ungkapan biasa, ia ternyata lebih mudah daripada yang kelihatan pada pandangan pertama.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION