Sprievodca uniknutím znakov v prostredí Java RegExps

1. Prehľad

Rozhranie API pre regulárne výrazy v Jave, java.util.regex sa často používa na porovnávanie vzorov. Ak chcete zistiť viac, môžete sledovať tento článok.

V tomto článku sa zameriame na únik znakov pomocou regulárneho výrazu a ukážeme si, ako je to možné v prostredí Java.

2. Špeciálne znaky RegExp

Podľa dokumentácie API pre regulárne výrazy Java je v regulárnom výraze sada špeciálnych znakov známych aj ako metaznaky.

Ak chceme postavám dovoliť také, aké sú, namiesto toho, aby sme ich interpretovali s ich špeciálnymi významami, musíme im uniknúť. Uniknutím týchto znakov vynútime, aby sa s nimi pri porovnávaní reťazca s daným regulárnym výrazom zaobchádzalo ako s bežnými znakmi.

Metaznaky, ktorým zvyčajne musíme uniknúť týmto spôsobom, sú:

Pozrime sa na jednoduchý príklad kódu, kde sa zhodujeme so vstupom String so vzorom vyjadreným v regulárnom výraze.

Tento test ukazuje, že pre daný vstupný reťazec foof keď vzor foo. (foo končiaci bodkovým znakom) sa zhoduje, vráti hodnotu pravda čo naznačuje, že zápas je úspešný.

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

Možno by vás zaujímalo, prečo je zhoda úspešná, keď na vstupe nie je žiadny bodkový (.) Znak Reťazec?

Odpoveď je jednoduchá. Bodka (.) Je metaznak - tu má mimoriadny význam to, že na jej mieste môže byť „akýkoľvek znak“. Preto je jasné, ako zodpovedajúci hráč určil, že sa zhoda nájde.

Povedzme, že nechceme zaobchádzať s bodkovým (.) Znakom s jeho jedinečným významom. Namiesto toho chceme, aby sa to interpretovalo ako bodka. To znamená, že v predchádzajúcom príklade nechceme nechať vzor foo. mať na vstupe zhodu String.

Ako by sme riešili takúto situáciu? Odpoveď je: musíme uniknúť zo znaku bodka (.), aby sa jeho špeciálny význam ignoroval.

Poďme sa tomu venovať podrobnejšie v nasledujúcej časti.

3. Unikajúce znaky

Podľa dokumentácie Java API pre regulárne výrazy existujú dva spôsoby, ako môžeme uniknúť znakom, ktoré majú špeciálny význam. Inými slovami, prinútiť ich, aby s nimi bolo zaobchádzané ako s bežnými znakmi.

Pozrime sa, aké to sú:

  1. Predchádzajte metaznaku pomocou spätnej lomky (\)
  2. Priložte metaznak s \ Q a \ E

To len znamená, že v príklade, ktorý sme videli skôr, ak chceme uniknúť z bodkového znaku, musíme pred znak bodky vložiť znak spätného lomítka. Alternatívne môžeme bodkový znak umiestniť medzi \ Q a \ E.

3.1. Únik pomocou spätného lomítka

Toto je jedna z techník, ktorou môžeme uniknúť metaznakom v regulárnom výraze. Vieme však, že spätná lomka je v Jave znakom escape String literály tiež. Preto musíme znak spätného lomítka zdvojnásobiť, keď ho použijeme pred akýmkoľvek znakom (vrátane samotného znaku \).

Preto v našom príklade musíme zmeniť regulárny výraz, ako je uvedené v tomto teste:

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

Tu je znak bodky uniknutý, takže porovnávač s ním jednoducho zaobchádza ako s bodkou a snaží sa nájsť vzor, ​​ktorý končí bodkou (t.j. foo.).

V takom prípade sa vráti nepravdivé pretože vo vstupe nie je zhoda String pre ten vzor.

3.2. Únik pomocou \ Q & \ E

Prípadne môžeme použiť \ Q a \ E uniknúť špeciálnemu znaku. \ Q označuje, že všetky znaky majú najviac \ E treba utiecť a \ E znamená, že musíme ukončiť únik, s ktorým sa začalo \ Q.

To len znamená, že čokoľvek je medzi tým \ Q a \ E by uniklo.

V zobrazenom teste je split () z String trieda vykoná zhodu pomocou regulárneho výrazu, ktorý je jej poskytnutý.

Našou požiadavkou je rozdeliť vstupný reťazec podľa znaku pipe (|) na slová. Preto na to používame vzor regulárneho výrazu.

Znak fajky je metaznak, ktorému je potrebné v regulárnom výraze uniknúť.

Únik sa tu vykonáva tak, že sa medzi ne umiestni znak rúry \ Q a \ E:

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

4. The Pattern.quote (Reťazec S) Metóda

Metóda Pattern.Quote (String S) v systéme Windows java.util.regex.Vzor trieda prevedie daný vzor regulárneho výrazu String do doslovného vzoru String. To znamená, že všetky metaznaky vo vstupe String sa považujú za bežné znaky.

Použitie tejto metódy by bolo pohodlnejšou alternatívou ako použitie \ Q & \ E ako to zabaľuje dané String s nimi.

Pozrime sa na túto metódu v akcii:

Bar @Test public void givenRegexWithPipeEscQuoteMeth_whenSplitStr_thenSplits ()

V tomto rýchlom teste Pattern.quote () metóda sa používa na únik z daného regexového vzoru a jeho transformáciu na a String doslovne. Inými slovami, uniká všetkým metaznakom prítomným vo vzorci regulárneho výrazu pre nás. Robí podobnú prácu ako \ Q & \ E.

Znak potrubia je uniknutý znakom Pattern.quote () metóda a split () interpretuje ako a String doslovný, ktorým vydelí vstup.

Ako vidíme, jedná sa o oveľa čistejší prístup a takisto si vývojári nemusia pamätať všetky únikové sekvencie.

Mali by sme si to všimnúť Vzor. Citát uzatvára celý blok jedinou únikovou sekvenciou. Ak by sme chceli uniknúť jednotlivým znakom, museli by sme použiť algoritmus nahradenia tokenu.

5. Ďalšie príklady

Pozrime sa, ako nahradiť všetko() metóda java.util.regex.Matcher Tvorba.

Ak potrebujeme nahradiť všetky výskyty daného znaku String s iným môžeme túto metódu použiť tak, že jej odovzdáme regulárny výraz.

Predstavte si, že máme vstup s viacerými výskytmi $ znak. Výsledok, ktorý chceme získať, je rovnaký reťazec s parametrom $ znak nahradený £.

Tento test demonštruje, ako je na tom vzor $ je odovzdaný bez úniku:

@Test public void givenRegexWithDollar_whenReplacing_thenNotReplace () {String strInput = "Dal som svojmu bratovi 50 dolárov." + "Kúpil cukrík za 35 dolárov. Teraz mu zostáva 15 dolárov."; Reťazec strRegex = "$"; Reťazec strReplacement = "£"; Reťazcový výstup = "Dal som £ 50 bratovi." + "Kúpil cukrík za 35 GBP. Teraz mu zostáva 15 GBP."; Vzor p = Pattern.compile (strRegex); Porovnávač m = p.matcher (strInput); assertThat (výstup, nie (equalTo (m.replaceAll (strReplacement)))); }

Test to tvrdí $ nie je správne nahradený £.

Teraz, ak unikneme vzoru regulárneho výrazu, k nahradeniu dôjde správne a test prejde, ako je znázornené v tomto útržku kódu:

@Test public void givenRegexWithDollarEsc_whenReplacing_thenReplace () {String strInput = "Dal som svojmu bratovi 50 dolárov." + "Kúpil cukrík za 35 dolárov. Teraz mu zostáva 15 dolárov."; Reťazec strRegex = "\ $"; Reťazec strReplacement = "£"; Reťazcový výstup = "Dal som £ 50 bratovi." + "Kúpil cukríky za 35 GBP. Teraz mu zostáva 15 GBP."; Vzor p = Pattern.compile (strRegex); Porovnávač m = p.matcher (strInput); assertEquals (výstup, m.replaceAll (strReplacement)); }

Všimnite si \\$ tu, čo robí trik uniknutím z $ znak a úspešne sa zhoduje so vzorom.

6. Záver

V tomto článku sme sa zaoberali unikajúcimi znakmi v regulárnych výrazoch v Jave.

Diskutovali sme o tom, prečo je potrebné pred regulárnymi výrazmi uniknúť, a o rôznych spôsoboch, ako ich možno dosiahnuť.

Zdrojový kód súvisiaci s týmto článkom nájdete ako vždy na serveri GitHub.


$config[zx-auto] not found$config[zx-overlay] not found