JavaRush /Java Blog /Random-TL /Mga Regular na Ekspresyon sa Java, Bahagi 2

Mga Regular na Ekspresyon sa Java, Bahagi 2

Nai-publish sa grupo
Nagpapakita kami sa iyong atensyon ng pagsasalin ng maikling gabay sa mga regular na expression sa Java, na isinulat ni Jeff Friesen para sa website ng javaworld . Para sa kadalian ng pagbabasa, hinati namin ang artikulo sa ilang bahagi. Mga Regular na Ekspresyon sa Java, Bahagi 2 - 1Mga Regular na Ekspresyon sa Java, Bahagi 1
Pinagsasama ang maraming hanay
Maaari mong pagsamahin ang maramihang mga hanay sa isang solong klase ng character na hanay sa pamamagitan ng paglalagay sa kanila nang magkatabi. Halimbawa, ang klase [a-zA-Z]ay tumutugma sa lahat ng Latin na alpabetikong character sa maliit o malaking titik.

Pinagsasama ang maraming hanay

Maaari mong pagsamahin ang maramihang mga hanay sa isang solong klase ng character na hanay sa pamamagitan ng paglalagay sa kanila nang magkatabi. Halimbawa, ang klase [a-zA-Z]ay tumutugma sa lahat ng Latin na alpabetikong character sa maliit o malaking titik.

Pagsasama-sama ng mga Klase ng Character

Ang isang character class union ay binubuo ng ilang nested na klase ng character at tumutugma sa lahat ng character sa resultang unyon. Halimbawa, ang klase [a-d[m-p]]ay tumutugma sa mga character mula asa papunta dat mula msa p. Isaalang-alang ang sumusunod na halimbawa: java RegexDemo [ab[c-e]] abcdef Hahanapin ng halimbawang ito ang mga character a, b, c, dat e, kung saan mayroong mga tugma sa abcdef:
regex = [ab[c-e]]
input = abcdef
Found [a] starting at 0 and ending at 0
Found [b] starting at 1 and ending at 1
Found [c] starting at 2 and ending at 2
Found [d] starting at 3 and ending at 3
Found [e] starting at 4 and ending at 4

Intersection ng klase ng character

Ang intersection ng mga klase ng character ay binubuo ng mga character na karaniwan sa lahat ng mga nested na klase at tumutugma lamang sa mga karaniwang character. Halimbawa, [a-z&&[d-f]]tumutugma ang klase sa mga character d, eat f. Isaalang-alang ang sumusunod na halimbawa: java RegexDemo "[aeiouy&&[y]]" party Tandaan na sa aking Windows operating system, kailangan ng dobleng panipi dahil tinatrato ng command shell ang mga ito &bilang command separator. Hahanapin lang ng halimbawang ito ang character yna may tugma sa party:
regex = [aeiouy&&[y]]
input = party
Found [y] starting at 4 and ending at 4

Pagbabawas ng mga klase ng character

Ang pagbabawas ng mga klase ng character ay binubuo ng lahat ng character maliban sa mga nasa nested na klase ng character, at tumutugma lamang sa mga natitirang character. Halimbawa, ang klase [a-z&&[^m-p]]ay tumutugma sa mga character mula asa papunta lat qmula sa z: java RegexDemo "[a-f&&[^a-c]&&[^e]]" abcdefg Hahanapin ng halimbawang ito ang mga character dat fkung saan mayroong mga tugma sa abcdefg:
regex = [a-f&&[^a-c]&&[^e]]
input = abcdefg
Found [d] starting at 3 and ending at 3
Found [f] starting at 5 and ending at 5

Mga Paunang Natukoy na Klase ng Character

Ang ilang mga klase ng character ay madalas na lumilitaw sa mga regular na expression upang bigyang-katwiran ang paggamit ng shorthand notation. Nag-aalok ang klase Patternng mga paunang natukoy na klase ng character bilang mga naturang pagdadaglat. Maaari mong gamitin ang mga ito upang pasimplehin ang iyong mga regular na expression at mabawasan ang mga error sa syntax. Mayroong ilang mga kategorya ng mga paunang natukoy na klase ng character: pamantayan, POSIX, java.lang.Characterat mga katangian ng Unicode tulad ng script, block, kategorya, at binary. Ang sumusunod na listahan ay nagpapakita lamang ng kategorya ng mga karaniwang klase:
  • \d: Numero. Katumbas [0-9].
  • \D: Hindi numeric na character. Katumbas [^0-9].
  • \s: Whitespace na character. Katumbas [ \t\n\x0B\f\r].
  • \S: Hindi isang whitespace na character. Katumbas [^\s].
  • \w: Simbolo na bumubuo ng salita. Katumbas [a-zA-Z_0-9].
  • \W: Hindi isang character na bumubuo ng salita. Katumbas [^\w].
Ang sumusunod na halimbawa ay gumagamit ng isang paunang natukoy na klase ng character \wupang ilarawan ang lahat ng mga character ng salita sa input text: java RegexDemo \w "aZ.8 _" Tingnang mabuti ang mga sumusunod na resulta ng pagpapatupad, na nagpapakita na ang mga character na tuldok at espasyo ay hindi itinuturing na mga character ng salita:
regex = \w
input = aZ.8 _
Found [a] starting at 0 and ending at 0
Found [Z] starting at 1 and ending at 1
Found [8] starting at 3 and ending at 3
Found [_] starting at 5 and ending at 5
Mga separator ng linya
Inilalarawan ng dokumentasyon ng class SDK Patternang dot metacharacter bilang isang paunang natukoy na klase ng character na tumutugma sa anumang character maliban sa mga line separator (isa o dalawang character na sequence na nagmamarka sa dulo ng isang linya). Ang exception ay dotall mode (na tatalakayin natin sa susunod), kung saan ang mga tuldok ay tumutugma din sa mga line separator. Tinutukoy ng klase Patternang mga sumusunod na line separator:
  • character ng pagbabalik ng karwahe ( \r);
  • newline character (simbolo para sa pagsulong ng papel sa isang linya) ( \n);
  • isang carriage return character na agad na sinusundan ng isang newline na character ( \r\n);
  • susunod na linya ng character ( \u0085);
  • character ng line separator ( \u2028);
  • simbolo ng separator ng talata ( \u2029)

Mga nakunan na grupo

Ang pangkat ng pagkuha ay ginagamit upang i-save ang nahanap na hanay ng mga character para sa karagdagang paggamit kapag naghahanap ayon sa pattern. Ang construct na ito ay isang sequence ng mga character na nakapaloob sa metacharacter sa pamamagitan ng panaklong ( ( )). Ang lahat ng mga character sa loob ng nakunan na pangkat ay itinuturing bilang isang solong kabuuan kapag naghahanap ayon sa pattern. Halimbawa, Javapinagsasama-sama ng pangkat ng pagkuha ( ) ang mga titik J, a, vat asa isang yunit. Hinahanap ng grupong ito ng pagkuha ang lahat ng paglitaw ng pattern Javasa input text. Sa bawat tugma, ang mga dating nakaimbak na character Javaay papalitan ng mga susunod. Maaaring ma-nest ang mga nakuhang grupo sa iba pang mga nakunan na grupo. Halimbawa, sa isang regular na expression, (Java( language))ang isang grupo (language)ay naka-nest sa loob ng isang grupo (Java). Ang bawat nested o non-nested capture group ay bibigyan ng isang numero, simula sa 1, at ang pagnunumero ay mula kaliwa hanggang kanan. Sa nakaraang halimbawa, (Java( language))tumutugma sa pagkuha ng pangkat na numero 1 at (language)tumutugma sa pagkuha ng pangkat na numero 2. Sa regular na expression (a)(b), (a)tumutugma sa pagkuha ng pangkat na numero 1 at (b)pagkuha ng pangkat na numero 2. Mga Regular na Ekspresyon sa Java, Bahagi 2 - 2Ang mga tugmang naka-imbak ng mga pangkat ng pagkuha ay maaaring ma-access sa ibang pagkakataon gamit ang mga backreference. Tinukoy bilang isang backslash na character na sinusundan ng isang numerong karakter na tumutugma sa bilang ng pangkat na kinukuha, ang backreference ay nagbibigay-daan sa iyo na sumangguni sa mga character sa tekstong nakunan ng grupo. Ang pagkakaroon ng backlink ay nagiging sanhi ng pagtutugma na sumangguni sa naka-imbak na resulta ng paghahanap ng nakuhang pangkat batay sa numero mula dito, at pagkatapos ay gamitin ang mga character mula sa resultang iyon upang subukan ang karagdagang paghahanap. Ipinapakita ng sumusunod na halimbawa ang paggamit ng isang backreference upang maghanap ng mga error sa gramatika sa teksto: Gumagamit java RegexDemo "(Java( language)\2)" "The Java language language" ang halimbawang ito (Java( language)\2)ng isang regular na expression upang makahanap ng isang error sa gramatika na may duplicate na salita languagena kaagad na sumusunod Javasa input text "The Java language language". Tinutukoy ng regular na expression na ito ang dalawang pangkat na kukunan: numero 1 – (Java( language)\2), katumbas ng Java language languageat numero 2 – (language), naaayon sa space character na sinusundan ng language. Ang backreference \2ay nagbibigay-daan sa nakaimbak na resulta ng pangkat na numero 2 na muling bisitahin upang ang matcher ay maaaring maghanap para sa pangalawang paglitaw ng isang puwang na sinusundan ng language, kaagad pagkatapos ng unang paglitaw ng isang puwang at language. Ang mga resulta ng matcher RegexDemoay ang mga sumusunod:
regex = (Java( language)\2)
input = The Java language language
Found [Java language language] starting at 4 and ending at 25

Mga tagatugma ng hangganan

Minsan kailangan mong magsagawa ng tugma ng pattern sa simula ng isang linya, sa mga hangganan ng salita, sa dulo ng teksto, atbp. Magagawa mo ito sa pamamagitan ng paggamit ng isa sa class edge matchers Pattern, na mga regular na expression construct na naghahanap ng mga tugma sa mga sumusunod na lokasyon:
  • ^: Simula ng linya;
  • $: Dulo ng linya;
  • \b: Hangganan ng salita;
  • \B: Hangganan ng pseudoword;
  • \A: Simula ng text;
  • \G: Pagtatapos ng nakaraang laban;
  • \Z: Katapusan ng text, hindi kasama ang trailing line separator (kung mayroon);
  • \z: Katapusan ng text
Ang sumusunod na halimbawa ay gumagamit ng ^boundary matcher metacharacter upang maghanap ng mga linya na nagsisimula sa The, na sinusundan ng zero o higit pang mga character ng salita: Tinukoy java RegexDemo "^The\w*" Therefore ng character ^na ang unang tatlong character ng input text ay dapat tumugma sa magkakasunod na pattern na character T, hat e, na maaaring sundan ng anumang numero ng mga simbolo na bumubuo ng salita. Narito ang resulta ng pagpapatupad:
regex = ^The\w*
input = Therefore
Found [Therefore] starting at 0 and ending at 8
Ano ang mangyayari kung palitan mo ang command line sa java RegexDemo "^The\w*" " Therefore"? Walang mahahanap na tugma dahil Thereforeang input text ay nauuna sa isang space character.

Walang tugma ang haba

Minsan, kapag nagtatrabaho sa mga edge matcher, makakatagpo ka ng zero-length na mga tugma. Совпадение нулевой длиныay isang tugma na hindi naglalaman ng anumang mga character. Maaaring mangyari ang mga ito sa walang laman na input text, sa simula ng input text, pagkatapos ng huling character ng input text, at sa pagitan ng alinmang dalawang character ng input text. Ang mga zero-length na tugma ay madaling makilala dahil palagi silang nagsisimula at nagtatapos sa parehong posisyon. Isaalang-alang ang sumusunod na halimbawa: java RegExDemo \b\b "Java is" Ang halimbawang ito ay naghahanap ng dalawang magkasunod na hangganan ng salita, at ang mga resulta ay ganito ang hitsura:
regex = \b\b
input = Java is
Found [] starting at 0 and ending at -1
Found [] starting at 4 and ending at 3
Found [] starting at 5 and ending at 4
Found [] starting at 7 and ending at 6
Nakikita namin ang ilang zero-length na tugma sa mga resulta. Ang mga posisyon sa pagtatapos dito ay mas mababa ng isa kaysa sa mga panimulang posisyon, dahil RegexDemotinukoy ko sa source code sa Listahan 1 end() – 1. Mga Regular na Ekspresyon sa Java, Bahagi 2 - 3

Mga Quantifier

Ang quantifier ay isang regular na construct ng expression na tahasan o implicit na nag-uugnay ng pattern sa isang numeric na value. Tinutukoy ng numeric value na ito kung gaano karaming beses hahanapin ang pattern. Ang mga quantifier ay nahahati sa sakim, tamad at sobrang sakim:
  • Ang matakaw na quantifier ( ?, *o +) ay idinisenyo upang mahanap ang pinakamahabang tugma. pwede po bang magtanong X? upang makahanap ng isa o mas kaunting mga paglitaw X, X*upang makahanap ng zero o higit pang mga pangyayari X, X+upang makahanap ng isa o higit pang mga pangyayari X, X{n}upang makahanap nng mga pangyayari X, X{n,}upang makahanap ng hindi bababa sa (at posibleng higit pa) nmga paglitaw , Xat X{n,m}upang makahanap ng hindi bababa sa nngunit hindi higit pang mmga paglitaw X.
  • Ang tamad na quantifier ( ??, *?o +?) ay idinisenyo upang mahanap ang pinakamaikling tugma. Maaari mong tukuyin X??upang maghanap ng isa o mas kaunting paglitaw ng X, X*? upang makahanap ng zero o higit pang mga pangyayari X, X+?upang mahanap ang isa o higit pang mga pangyayari X, X{n}?upang mahanap nang mga pangyayari X, X{n,}?upang makahanap ng hindi bababa sa (at posibleng higit pa) nmga pangyayari X, at X{n,m}?upang makahanap ng hindi bababa nsa ngunit hindi higit sa mmga pangyayari X.
  • Ang super-greedy quantifier ( ?+, *+o ++) ay katulad ng greedy quantifier, maliban na ang super-greedy quantifier ay gumagawa lamang ng isang pagtatangka upang mahanap ang pinakamahabang tugma, habang ang greedy quantifier ay maaaring gumawa ng maraming pagsubok. Maaaring itakda X?+upang mahanap ang isa o mas kaunting mga paglitaw X, X*+upang makahanap ng zero o higit pang mga paglitaw X, X++upang makahanap ng isa o higit pang mga paglitaw X, X{n}+upang makahanap nng mga paglitaw ng X, X{n,}+upang makahanap ng hindi bababa sa (at posibleng higit pa) nmga paglitaw , Xat X{n,m}+ upang makahanap ng hindi bababa sa nngunit hindi hihigit sa mmga paglitaw X.
Ang sumusunod na halimbawa ay naglalarawan ng paggamit ng matakaw na quantifier: java RegexDemo .*ox "fox box pox" Narito ang mga resulta:
regex = .*ox
input = fox box pox
Found [fox box pox] starting at 0 and ending at 10
.*Hinahanap ng greedy quantifier ( ) ang pinakamahabang sequence ng mga character na nagtatapos sa ox. Kinukonsumo nito ang buong input text at pagkatapos ay i-roll back hanggang sa makita nito na ang input text ay nagtatapos sa mga character na ito. Tingnan natin ngayon ang tamad na quantifier: java RegexDemo .*?ox "fox box pox" Ang mga resulta nito:
regex = .*?ox
input = fox box pox
Found [fox] starting at 0 and ending at 2
Found [ box] starting at 3 and ending at 6
Found [ pox] starting at 7 and ending at 10
.*?Hinahanap ng lazy quantifier ( ) ang pinakamaikling pagkakasunod-sunod ng mga character na nagtatapos sa ox. Nagsisimula ito sa isang blangkong string at unti-unting kumonsumo ng mga character hanggang sa makahanap ito ng katugma. At pagkatapos ay patuloy na gumagana hanggang sa maubos ang input text. Sa wakas, tingnan natin ang super-greedy quantifier: java RegexDemo .*+ox "fox box pox" At narito ang mga resulta nito:
regex = .*+ox
input = fox box pox
Ang sobrang sakim na quantifier ( .*+) ay hindi nakakahanap ng mga tugma dahil kinokonsumo nito ang lahat ng input text at wala nang maitutugma oxsa dulo ng regular na expression. Hindi tulad ng greedy quantifier, ang super-greedy quantifier ay hindi bumabalik.

Walang tugma ang haba

Minsan kapag nagtatrabaho sa mga quantifier ay makakatagpo ka ng mga zero-length na tugma. Halimbawa, ang paggamit ng sumusunod na greedy quantifier ay nagreresulta sa maramihang zero-length na tugma: java RegexDemo a? abaa Ang mga resulta ng pagpapatakbo ng halimbawang ito:
regex = a?
input = abaa
Found [a] starting at 0 and ending at 0
Found [] starting at 1 and ending at 0
Found [a] starting at 2 and ending at 2
Found [a] starting at 3 and ending at 3
Found [] starting at 4 and ending at 3
Mayroong limang laban sa mga resulta ng pagpapatupad. Bagama't ang una, ikatlo at ikaapat ay lubos na inaasahan (ang mga ito ay tumutugma sa mga posisyon ng tatlong titik asa abaa), ang pangalawa at panglima ay maaaring mabigla sa iyo. Tila kung ipinapahiwatig nila kung ano aang tumutugma bsa dulo ng teksto, ngunit sa katotohanan ay hindi ito ang kaso. Ang regular na expression a?ay hindi naghahanap bsa dulo ng teksto. Hinahanap nito ang presensya o kawalan a. Kapag a?hindi nito nahanap ang a, iuulat ito bilang isang zero-length na tugma.

Mga nested flag expression

Gumagawa ang mga matcher ng ilang default na pagpapalagay na maaaring ma-override kapag kino-compile ang regular na expression sa isang pattern. Tatalakayin natin ang isyung ito mamaya. Nagbibigay-daan sa iyo ang isang regular na expression na i-override ang alinman sa mga default gamit ang isang nested flag expression. Tinukoy ang regular na expression na ito bilang isang metacharacter ng mga panaklong sa paligid ng isang tandang pananong metacharacter ( ?), na sinusundan ng isang maliit na titik na Latin. PatternNauunawaan ng klase ang sumusunod na mga nested flag expression:
  • (?i): Pinapagana ang case-insensitive na pagtutugma ng pattern. Halimbawa, kapag gumagamit ng command, java RegexDemo (?i)tree Treehouseang pagkakasunod-sunod ng mga character Treeay tumutugma sa pattern tree. Ang default ay case-sensitive pattern search.
  • (?x): Pinapayagan ang paggamit ng mga whitespace na character at komento na nagsisimula sa metacharacter sa loob ng pattern #. Babalewalain ng matcher ang dalawa. Halimbawa, para sa java RegexDemo ".at(?x)#match hat, cat, and so on" matterisang pagkakasunod-sunod ng mga character matna tumutugma sa pattern .at. Bilang default, hindi pinapayagan ang mga whitespace na character at komento, at itinuturing sila ng matcher bilang mga character na kasangkot sa paghahanap.
  • (?s): Pinapagana ang dotall mode, kung saan ang tuldok na metacharacter ay tumutugma sa mga line separator bilang karagdagan sa anumang iba pang character. Halimbawa, ang command java RegexDemo (?s). \nay makakahanap ng isang newline na character. Ang default ay ang kabaligtaran ng dotall: walang mga line separator na makikita. Halimbawa, ang command Java RegexDemo . \nay hindi makakahanap ng isang newline na character.
  • (?m): Pinapagana ang multiline mode, kung saan ^tumutugma ito sa simula at $dulo ng bawat linya. Halimbawa, java RegexDemo "(?m)^abc$" abc\nabchinahanap ang parehong mga sequence sa input text abc. Bilang default, ginagamit ang single-line mode: ^tumutugma sa simula ng buong input text, at $tumutugma sa dulo nito. Halimbawa, java RegexDemo "^abc$" abc\nabcnagbabalik ng tugon na walang mga tugma.
  • (?u): Pinapagana ang Unicode-sensitive na case alignment. Ang flag na ito, kapag ginamit kasabay ng (?i), ay nagbibigay-daan para sa case-insensitive na pagtutugma ng pattern alinsunod sa pamantayan ng Unicode. Ang default na setting ay ang paghahanap para sa case-sensitive at US-ASCII na mga character lang.
  • (?d): Pinapagana ang Unix-style string mode, kung saan kinikilala ng matcher ang mga metacharacter sa konteksto ., ^at $tanging ang line separator \n. Ang default ay non-Unix style string mode: kinikilala ng matcher, sa konteksto ng mga metacharacter sa itaas, ang lahat ng line delimiter.
Ang mga nested flag expression ay kahawig ng mga nakunan na grupo dahil ang kanilang mga character ay napapalibutan ng parenthesis metacharacter. Hindi tulad ng mga na-capture na grupo, ang mga nested flag expression ay isang halimbawa ng mga hindi na-capture na grupo, na isang regular na pagbuo ng expression na hindi kumukuha ng mga text character. Ang mga ito ay tinukoy bilang mga pagkakasunud-sunod ng mga character na napapalibutan ng mga metacharacter ng panaklong.
Tinutukoy ang Maramihang Nested Flag Expression
Posibleng tumukoy ng maramihang mga nested na flag expression sa isang regular na expression sa pamamagitan ng paglalagay sa mga ito nang magkatabi ( (?m)(?i))) o paglalagay ng mga titik na tumutukoy sa mga ito nang sunud-sunod ( (?mi)).

Konklusyon

Tulad ng malamang na napagtanto mo na ngayon, ang mga regular na expression ay lubhang kapaki-pakinabang at nagiging mas kapaki-pakinabang habang pinagkadalubhasaan mo ang mga nuances ng kanilang syntax. Sa ngayon ay ipinakilala ko sa iyo ang mga pangunahing kaalaman ng mga regular na expression at ang Pattern. Sa Bahagi 2, titingnan natin nang mas malalim ang Regex API at tuklasin ang mga pamamaraan ng Pattern, Matcherat PatternSyntaxException. Ipapakita ko rin sa iyo ang dalawang praktikal na aplikasyon ng Regex API na magagamit mo kaagad sa iyong mga programa. Mga Regular na Ekspresyon sa Java, Bahagi 3 Mga Regular na Ekspresyon sa Java, Bahagi 4 Mga Regular na Ekspresyon sa Java, Bahagi 5
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION