Panduan untuk Melarikan Karakter di Java RegExps

1. Gambaran keseluruhan

API ekspresi biasa di Java, java.util.regex banyak digunakan untuk pemadanan corak. Untuk mengetahui lebih lanjut, anda boleh mengikuti artikel ini.

Dalam artikel ini, kita akan memfokuskan diri untuk melarikan diri dari karakter dengan ekspresi biasa dan menunjukkan bagaimana ia dapat dilakukan di Java.

2. Watak RegExp Khas

Menurut dokumentasi API ekspresi biasa Java, ada sekumpulan karakter khas yang juga dikenal sebagai metacharacters yang hadir dalam ekspresi biasa.

Apabila kita mahu membiarkan watak-watak itu sebagai gantinya daripada menafsirkannya dengan makna khasnya, kita perlu melepaskannya. Dengan melepaskan watak-watak ini, kami memaksa mereka diperlakukan sebagai watak biasa ketika memadankan rentetan dengan ekspresi biasa yang diberikan.

Metakarakter yang biasanya kita perlukan untuk melarikan diri dengan cara ini adalah:

Mari kita lihat contoh kod ringkas di mana kita memadankan String input dengan corak yang dinyatakan dalam ungkapan biasa.

Ujian ini menunjukkan bahawa yang diberikan rentetan input Foof apabila corak foo . ( foo yang diakhiri dengan watak titik) dipadankan, ia mengembalikan nilai benar yang menunjukkan bahawa perlawanan berjaya.

@Test public void givenRegexWithDot_whenMatchingStr_thenMatches() { String strInput = "foof"; String strRegex = "foo."; assertEquals(true, strInput.matches(strRegex)); }

Anda mungkin tertanya-tanya mengapa perlawanan berjaya apabila tidak ada watak titik (.) Dalam String input ?

Jawapannya mudah. Titik (.) Adalah watak metakarakter - kepentingan khas titik di sini ialah terdapat 'watak apa pun' di tempatnya. Oleh itu, jelas bagaimana penjodoh menentukan bahawa perlawanan dijumpai.

Katakan bahawa kita tidak mahu memperlakukan watak titik (.) Dengan makna yang unik. Sebaliknya, kami mahu ia ditafsirkan sebagai tanda titik. Ini bermaksud bahawa dalam contoh sebelumnya, kita tidak mahu membiarkan corak itu tidak betul . untuk mempunyai padanan dalam String input .

Bagaimana kita menangani situasi seperti ini? Jawapannya adalah: kita perlu melepaskan watak titik (.) Sehingga makna khasnya tidak diendahkan.

Mari gali dengan lebih terperinci di bahagian seterusnya.

3. Melarikan watak

Menurut dokumentasi Java API untuk ungkapan biasa, ada dua cara di mana kita dapat melepaskan watak yang mempunyai makna khusus. Dengan kata lain, untuk memaksa mereka diperlakukan sebagai watak biasa.

Mari lihat apa itu:

  1. Mendahului metakarakter dengan garis miring terbalik (\)
  2. Lampirkan metakarakter dengan \ Q dan \ E

Ini hanya bermaksud bahawa dalam contoh yang kita lihat sebelumnya, jika kita ingin melarikan diri dari watak titik, kita perlu meletakkan watak garis miring terbalik sebelum watak titik. Sebagai alternatif, kita boleh meletakkan watak titik di antara \ Q dan \ E.

3.1. Melarikan diri menggunakan Tanda Belakang

Ini adalah salah satu teknik yang dapat kita gunakan untuk melarikan diri dari metakarakter dalam ungkapan biasa. Namun, kita tahu bahawa watak garis miring terbalik adalah watak pelarian dalam literatur Java String juga. Oleh itu, kita perlu menggandakan watak garis miring terbalik ketika menggunakannya untuk mendahului watak apa pun (termasuk watak \ itu sendiri).

Oleh itu, dalam contoh kita, kita perlu mengubah ungkapan biasa seperti yang ditunjukkan dalam ujian ini:

@Test public void givenRegexWithDotEsc_whenMatchingStr_thenNotMatching() { String strInput = "foof"; String strRegex = "foo\\."; assertEquals(false, strInput.matches(strRegex)); }

Di sini, watak titik dilarikan, jadi pencocokan hanya memperlakukannya sebagai titik dan cuba mencari corak yang berakhir dengan titik (iaitu foo. ).

Dalam kes ini, ia kembali palsu kerana tidak ada padanan dalam String input untuk corak itu.

3.2. Melarikan diri Menggunakan \ Q & \ E

Sebagai alternatif, kita boleh menggunakan \ Q dan \ E untuk melarikan diri dari watak khas. \ Q menunjukkan bahawa semua watak-watak sehingga \ E perlu melarikan diri dan \ E bermakna kita perlu berakhir Melarikan diri yang telah dimulakan dengan \ Q .

Ini hanya bermaksud bahawa apa sahaja yang ada di antara \ Q dan \ E akan terlepas.

Dalam ujian yang ditunjukkan di sini, split () daripada String kelas melakukan perlawanan menggunakan ungkapan biasa yang diberikan kepadanya.

Keperluan kami adalah untuk memisahkan rentetan input dengan watak paip (|) menjadi kata-kata. Oleh itu, kami menggunakan corak ungkapan biasa untuk melakukannya.

Perwatakan paip adalah watak metakarakter yang perlu dilarikan dalam ungkapan biasa.

Di sini, pelarian dilakukan dengan meletakkan watak paip antara \ Q dan \ E :

@Test public void givenRegexWithPipeEscaped_whenSplitStr_thenSplits() \\E"; assertEquals(4, strInput.split(strRegex).length); 

4. Kaedah Pattern.quote (String S)

Kaedah Pattern.Quote (String S) dalam kelas java.util.regex.Pattern menukar corak ekspresi biasa String yang diberi menjadi String corak literal . Ini bermaksud bahawa semua metakarakter dalam String input diperlakukan sebagai watak biasa.

Menggunakan kaedah ini akan menjadi alternatif yang lebih mudah daripada menggunakan \ Q & \ E kerana ia membungkus String yang diberikan dengan mereka.

Mari lihat kaedah ini dalam tindakan:

@Test public void givenRegexWithPipeEscQuoteMeth_whenSplitStr_thenSplits() bar

Dalam ujian pantas ini, kaedah Pattern.quote () digunakan untuk melarikan diri dari pola regex yang diberikan dan mengubahnya menjadi String literal. Dengan kata lain, ia melarikan diri dari semua metakarakter yang terdapat dalam corak regex bagi kita. Ia melakukan kerja yang sama dengan \ Q & \ E .

Karakter paip dilarikan dengan kaedah Pattern.quote () dan split () menafsirkannya sebagai String literal di mana ia membahagi input.

Seperti yang kita lihat, ini adalah pendekatan yang jauh lebih bersih dan juga pembangun tidak perlu mengingat semua urutan pelarian.

Kita harus perhatikan bahawa Pattern.quote merangkumi keseluruhan blok dengan satu urutan pelarian. Sekiranya kita ingin melarikan diri watak secara individu, kita perlu menggunakan algoritma penggantian token.

5. Contoh Tambahan

Mari kita lihat bagaimana replaceAll () kaedah java.util.regex.Matcher berfungsi.

Sekiranya kita perlu mengganti semua kejadian String watak tertentu dengan String yang lain, kita dapat menggunakan kaedah ini dengan menyampaikan ekspresi biasa kepadanya.

Bayangkan kita mempunyai input dengan pelbagai kejadian watak $ . Hasil yang ingin kita dapatkan adalah rentetan yang sama dengan watak $ digantikan dengan £.

Ujian ini menunjukkan bagaimana corak $ dilalui tanpa terlepas:

@Test public void givenRegexWithDollar_whenReplacing_thenNotReplace() { String strInput = "I gave $50 to my brother." + "He bought candy for $35. Now he has $15 left."; String strRegex = "$"; String strReplacement = "£"; String output = "I gave £50 to my brother." + "He bought candy for £35. Now he has £15 left."; Pattern p = Pattern.compile(strRegex); Matcher m = p.matcher(strInput); assertThat(output, not(equalTo(m.replaceAll(strReplacement)))); }

Ujian tersebut menegaskan bahawa $ tidak diganti dengan betul dengan £ .

Sekarang jika kita keluar dari corak regex, penggantian berlaku dengan betul, dan ujian lulus seperti yang ditunjukkan dalam coretan kod ini:

@Test public void givenRegexWithDollarEsc_whenReplacing_thenReplace() { String strInput = "I gave $50 to my brother." + "He bought candy for $35. Now he has $15 left."; String strRegex = "\\$"; String strReplacement = "£"; String output = "I gave £50 to my brother." + "He bought candy for £35. Now he has £15 left."; Pattern p = Pattern.compile(strRegex); Matcher m = p.matcher(strInput); assertEquals(output,m.replaceAll(strReplacement)); }

Perhatikan \\ $ di sini, yang melakukan silap mata dengan melarikan watak $ dan berjaya memadankan corak.

6. Kesimpulannya

Dalam artikel ini, kami melihat watak yang melarikan diri dalam ekspresi biasa di Java.

Kami membincangkan mengapa ungkapan biasa perlu dilarikan, dan cara yang berbeza di mana ia dapat dicapai.

Seperti biasa, kod sumber yang berkaitan dengan artikel ini boleh didapati di GitHub.