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

Mga Regular na Ekspresyon sa Java, Bahagi 3

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 3 - 1Mga Regular na Ekspresyon sa Java, Bahagi 1 Mga Regular na Ekspresyon sa Java, Bahagi 2

Pasimplehin ang mga karaniwang gawain sa programming gamit ang Regex API

Sa Bahagi 1 at 2 ng artikulong ito, ipinakilala sa iyo ang mga regular na expression at ang Regex API. Natutunan mo ang tungkol sa klase Patternat dumaan sa mga halimbawang nagpapakita ng mga regular na expression na construct, mula sa simpleng pagtutugma ng pattern gamit ang mga literal na string hanggang sa mas kumplikadong pagtutugma gamit ang mga range, boundary matcher, at quantifier. Sa ito at sa mga susunod na bahagi ay isasaalang-alang natin ang mga isyung hindi saklaw sa unang bahagi, pag-aaralan natin ang mga kaukulang pamamaraan ng mga klase Pattern, Matcherat PatternSyntaxException. Matututuhan mo rin ang dalawang utility na gumagamit ng mga regular na expression upang gawing mas madali ang mga karaniwang problema sa programming. Ang una ay kumukuha ng mga komento mula sa code para sa dokumentasyon. Ang pangalawa ay isang library ng reusable code na idinisenyo upang magsagawa ng lexical analysis - isang mahalagang bahagi ng mga assembler, compiler, at katulad na software.

PAGDdownload ng SOURCE CODE

Makukuha mo ang lahat ng source code (nilikha ni Jeff Friesen para sa JavaWorld) para sa mga demo application sa artikulong ito mula dito .

Pag-aaral ng Regex API

Pattern, Matcherat PatternSyntaxExceptionang tatlong klase na bumubuo sa Regex API. Ang bawat isa sa kanila ay nagbibigay ng mga pamamaraan na nagbibigay-daan sa iyong gumamit ng mga regular na expression sa iyong code.

Mga pamamaraan ng klase ng Pattern

Ang isang instance ng isang klase Patternay isang pinagsama-samang regular na expression, na kilala rin bilang isang pattern. Ang mga regular na expression ay pinagsama-sama upang mapabuti ang pagganap ng mga pagpapatakbo ng pagtutugma ng pattern. Ang mga sumusunod na static na pamamaraan ay sumusuporta sa compilation.
  • Pattern compile(String regex)kino-compile ang nilalaman regexsa isang intermediate na representasyon na nakaimbak sa isang bagong Pattern. Ang pamamaraang ito ay nagbabalik ng isang reference sa isang bagay kung matagumpay, o naghagis ng isang pagbubukod PatternSyntaxExceptionkung may nakitang di-wastong syntax ng regular na expression. Ang anumang object ng klase Matcherna ginamit Patterno ibinalik mula sa object na ito ay gumagamit ng mga default na setting nito, gaya ng case-sensitive na paghahanap. Bilang halimbawa, ang code snippet Pattern p = Pattern.compile("(?m)^\\."); ay gumagawa ng isang bagay Patternna nag-iimbak ng pinagsama-samang representasyon ng isang regular na expression upang tumugma sa mga string na nagsisimula sa isang tuldok na character.

  • Pattern compile(String regex, int flags)nilulutas ang parehong problema bilang Pattern compile(String regex), ngunit isinasaalang-alang flags: isang set ng mga bit constant para sa mga bit na flag ng uri ng OR. Ang klase Patternay nagdedeklara ng mga constant CANON_EQ, CASE_INSENSITIVE, COMMENTS, DOTALL, LITERAL, MULTILINE, UNICODE_CASE, UNICODE_CHARACTER_CLASS и UNIX_LINESna maaaring pagsamahin gamit ang bitwise OR (halimbawa, CASE_INSENSITIVE | DOTALL) at ipinasa bilang argumento flags.

  • Maliban sa CANON_EQ, LITERAL и UNICODE_CHARACTER_CLASS, ang mga constant na ito ay isang alternatibo sa mga nested na expression ng flag na ipinakita sa Part 1. Kung ang isang flag constant maliban sa tinukoy sa klase ay nakatagpo Pattern, ang pamamaraan Pattern compile(String regex, int flags) ay naghagis ng isang exception java.lang.IllegalArgumentException. Halimbawa, Pattern p = Pattern.compile("^\\.", Pattern.MULTILINE);katumbas ng nakaraang halimbawa, na ang pare-pareho Pattern.MULTILINEat ang nested flag na expression (?m)ay gumagawa ng parehong bagay.
Minsan kinakailangan na kumuha ng kopya ng orihinal na string ng isang regular na expression na pinagsama-sama sa isang bagay Pattern, kasama ang mga flag na ginagamit nito. Upang gawin ito, maaari mong tawagan ang mga sumusunod na pamamaraan:
  • String pattern()ibinabalik ang orihinal na string ng regular na expression na pinagsama-sama sa isang Pattern.

  • int flags()ibinabalik ang mga flag ng object Pattern.
Pagkatapos matanggap ang object Pattern, ito ay karaniwang ginagamit para makuha ang object Matcherpara magsagawa ng pattern matching operations. Ang pamamaraan Matcher matcher(Charsequence input)ay lumilikha ng isang bagay Matcherna naghahanap ng teksto inputpara sa isang tugma sa isang pattern ng bagay Pattern. Kapag tinawag, nagbabalik ito ng reference sa object na ito Matcher. Halimbawa, ang utos Matcher m = p.matcher(args[1]);ay nagbabalik Matcherpara sa bagay Patternna isinangguni ng variable p.
Isang beses na paghahanap
Ang paraan ng static boolean matches(String regex, CharSequence input)klase Patternay nagbibigay-daan sa iyo upang makatipid sa paglikha ng mga bagay Patternat Matcherisang beses na paghahanap gamit ang isang template. Ang pamamaraang ito ay nagbabalik ng true kung inputang pattern ay tumugma regex, kung hindi, ito ay nagbabalik ng false. Kung ang regular na expression ay naglalaman ng isang syntax error, ang pamamaraan ay naghagis ng isang pagbubukod PatternSyntaxException. Halimbawa, System.out.println(Pattern.matches("[a-z[\\s]]*", "all lowercase letters and whitespace only"));prints true, na nagpapatunay na ang parirala all lowercase letters and whitespace onlyay naglalaman lamang ng mga puwang at maliliit na character.
Mga Regular na Ekspresyon sa Java, Bahagi 3 - 2

Paghahati ng teksto

Karamihan sa mga developer ay may kahit isang beses na nakasulat na code upang hatiin ang input text sa mga bahaging bahagi nito, tulad ng pag-convert ng isang text-based na empleyado na account sa isang hanay ng mga field. Ang klase Patternay nagbibigay ng kakayahang mas maginhawang lutasin ang nakakapagod na gawaing ito gamit ang dalawang paraan ng paghahati ng teksto:
  • Ang pamamaraan String[] split(CharSequence text, int limit)ay nahahati textayon sa nahanap na mga tugma sa object pattern Patternat ibinabalik ang mga resulta sa isang array. Ang bawat elemento ng array ay tumutukoy ng isang text sequence na pinaghihiwalay mula sa susunod na sequence ng isang pattern-matching text fragment (o dulo ng text). Ang mga elemento ng array ay nasa parehong pagkakasunud-sunod kung saan lumilitaw ang mga ito sa text.

    Sa paraang ito, ang bilang ng mga elemento ng array ay nakadepende sa parameter limit, na kumokontrol din sa bilang ng mga tugmang makikita.

    • Ang isang positibong halaga ay naghahanap ng hindi hihigit sa limit-1mga tugma at ang haba ng array ay hindi hihigit sa limitmga elemento.
    • Kung negatibo ang value, hahanapin ang lahat ng posibleng tugma, at maaaring maging arbitrary ang haba ng array.
    • Kung zero ang value, hahanapin ang lahat ng posibleng tugma, maaaring arbitraryo ang haba ng array, at itatapon ang mga walang laman na linya sa dulo.

  • Tinatawag ng pamamaraan String[] split(CharSequence text)ang nakaraang pamamaraan na may 0 bilang argumentong limitasyon at ibinabalik ang resulta ng tawag nito.
Nasa ibaba ang mga resulta ng pamamaraan split(CharSequence text)para sa paglutas ng problema ng paghahati ng isang account ng empleyado sa magkakahiwalay na larangan ng pangalan, edad, postal address at suweldo:
Pattern p = Pattern.compile(",\\s");
String[] fields = p.split("John Doe, 47, Hillsboro Road, 32000");
for (int i = 0; i < fields.length; i++)
   System.out.println(fields[i]);
Ang code sa itaas ay naglalarawan ng isang regular na expression upang makahanap ng isang comma character na agad na sinusundan ng isang solong space character. Narito ang mga resulta ng pagpapatupad nito:
John Doe
47
Hillsboro Road
32000

Mga predicate ng template at ang Streams API

Sa Java 8, Patternlumitaw ang isang pamamaraan sa klase . Ang pamamaraang ito ay lumilikha ng isang predicate (isang function na may boolean value) na ginagamit upang tumugma sa pattern. Ang paggamit ng paraang ito ay ipinapakita sa sumusunod na snippet ng code: Predicate asPredicate()
List progLangs = Arrays.asList("apl", "basic", "c", "c++", "c#", "cobol", "java", "javascript", "perl", "python", "scala");
Pattern p = Pattern.compile("^c");
progLangs.stream().filter(p.asPredicate()).forEach(System.out::println);
Ang code na ito ay lumilikha ng isang listahan ng mga pangalan ng programming language, pagkatapos ay nag-compile ng isang pattern upang mahanap ang lahat ng mga pangalan na nagsisimula sa titik c. Ang huling linya ng code sa itaas ay nagpapatupad ng pagtanggap ng isang serial stream ng data na may listahang ito bilang pinagmulan. Nagse-set up ito ng filter gamit ang isang Boolean function asPredicate()na nagbabalik ng true kapag nagsimula ang pangalan sa isang titik cat umuulit sa stream, nagpi-print ng mga tumutugmang pangalan sa karaniwang output. Ang huling linyang ito ay katumbas ng sumusunod na regular na loop, pamilyar sa RegexDemo application mula sa Part 1:
for (String progLang: progLangs)
   if (p.matcher(progLang).find())
      System.out.println(progLang);

Mga pamamaraan ng klase ng matcher

Ang isang halimbawa ng klase Matcheray naglalarawan ng isang mekanismo para sa pagsasagawa ng pattern na pagtutugma ng mga operasyon sa isang sequence ng mga character sa pamamagitan ng pagbibigay-kahulugan sa pinagsama-samang regular na expression ng klase Pattern. Ang mga bagay ng klase Matcheray sumusuporta sa iba't ibang uri ng mga pagpapatakbo ng paghahanap ng pattern:
  • Hinahanap ng pamamaraan boolean find()ang input text para sa susunod na tugma. Ang pamamaraang ito ay nagsisimula sa pag-scan alinman sa simula ng tinukoy na teksto o sa unang character pagkatapos ng nakaraang tugma. Ang pangalawang opsyon ay posible lamang kung ang nakaraang tawag sa paraang ito ay bumalik na totoo at ang solver ay hindi na-reset. Sa anumang kaso, kung matagumpay ang paghahanap, ibabalik ang boolean value na true. Ang isang halimbawa ng pamamaraang ito ay matatagpuan sa RegexDemoBahagi 1.

  • Nire-reset ng pamamaraan boolean find(int start)ang matcher at hinahanap ang text para sa susunod na tugma. Nagsisimula ang pagtingin sa posisyong tinukoy ng parameter start. Kung matagumpay ang paghahanap, ibabalik ang boolean value na true. Halimbawa, m.find(1);ini-scan ang teksto simula sa posisyon 1(ang posisyon 0 ay binabalewala). Kung ang parameter startay naglalaman ng negatibong value o isang value na mas malaki kaysa sa matcher na haba ng text, ang paraan ay naghahatid ng exception java.lang.IndexOutOfBoundsException.

  • Sinusubukan ng pamamaraan boolean matches()na itugma ang lahat ng teksto sa isang pattern. Nagbabalik ito ng boolean value na true kung lahat ng text ay tumutugma sa pattern. Halimbawa, Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.matches());naglalabas ang code falsedahil ang karakter !ay hindi isang character na salita.

  • Sinusubukan ng pamamaraan boolean lookingAt()na itugma ang tinukoy na teksto sa pattern. Ang pamamaraang ito ay nagbabalik ng totoo kung anumang bahagi ng teksto ang tumutugma sa pattern. Hindi tulad ng pamamaraan matches();, ang lahat ng teksto ay hindi kailangang tumugma sa pattern. Halimbawa, Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.lookingAt());maglalabas ito ng true, dahil ang simula ng teksto abc!ay binubuo lamang ng mga character na bumubuo ng salita.

Hindi tulad ng mga bagay sa klase Pattern, ang mga bagay sa klase Matcheray nagpapanatili ng impormasyon ng estado. Minsan maaaring kailanganin mong i-reset ang matcher upang i-clear ang impormasyong ito pagkatapos matapos ang paghahanap ng pattern. Ang mga sumusunod na paraan ay magagamit upang i-reset ang solver:
  • Nire-reset ng pamamaraan Matcher reset()ang estado ng matcher, kasama ang posisyong idaragdag sa dulo (i-reset sa 0). Ang susunod na operasyon ng paghahanap ng pattern ay magsisimula sa simula ng teksto ng matcher. Nagbabalik ng reference sa kasalukuyang object Matcher. Halimbawa, m.reset();ni-reset ang solver na isinangguni ng m.

  • Nire-reset ng pamamaraan Matcher reset(CharSequence text)ang estado ng solver at itinatakda ang bagong teksto ng solver sa text. Ang susunod na operasyon ng paghahanap ng pattern ay magsisimula sa simula ng bagong teksto ng matcher. Nagbabalik ng reference sa kasalukuyang object Matcher. Halimbawa, m.reset("new text");nire-reset ang isinangguni na resolver mat itinatakda ang bagong solver na text sa "new text".

Mga Regular na Ekspresyon sa Java, Bahagi 3 - 3

Pagdaragdag ng teksto sa dulo

Ang posisyon ng matcher na idaragdag sa dulo ay tumutukoy sa simula ng matcher na text na nakadugtong sa dulo ng object ng uri java.lang.StringBuffer. Ginagamit ng mga sumusunod na pamamaraan ang posisyong ito:
  • Binabasa ng pamamaraan Matcher appendReplacement(StringBuffer sb, String replacement)ang mga character na teksto ng matcher at idinadagdag ang mga ito sa dulo ng bagay StringBufferna tinutukoy ng argumento sb. Ang pamamaraang ito ay humihinto sa pagbabasa sa huling karakter bago ang nakaraang pagtutugma ng pattern. Susunod, ang pamamaraan ay nagdaragdag ng mga character mula sa object ng uri Stringna isinangguni ng argumento replacementhanggang sa dulo ng object StringBuffer(ang string replacementay maaaring maglaman ng mga reference sa mga pagkakasunud-sunod ng teksto na nakuha sa nakaraang paghahanap; ang mga ito ay tinukoy gamit ang mga character ($)at numero ng pangkat na nakunan). Sa wakas, itinatakda ng pamamaraan ang halaga ng posisyon ng matcher upang idugtong sa posisyon ng huling katugmang character kasama ang isa, at pagkatapos ay ibabalik ang isang reference sa kasalukuyang matcher.

  • Ang pamamaraan Matcher appendReplacement(StringBuffer sb, String replacement)ay nagtatapon ng isang pagbubukod java.lang.IllegalStateExceptionkung ang tumutugma ay hindi pa nakakahanap ng isang tugma o isang nakaraang pagtatangka sa paghahanap ay nabigo. Naglalagay ito ng pagbubukod IndexOutOfBoundsExceptionkung ang linya replacementay tumutukoy sa isang pangkat ng pagkuha na wala sa pattern).

  • Ang pamamaraan StringBuffer appendTail(StringBuffer sb)ay nagdaragdag ng lahat ng teksto sa isang bagay StringBufferat nagbabalik ng isang sanggunian sa bagay na iyon. Pagkatapos ng huling tawag sa pamamaraan appendReplacement(StringBuffer sb, String replacement), tawagan ang paraan appendTail(StringBuffer sb)upang kopyahin ang natitirang teksto sa bagay StringBuffer.

Mga nakunan na grupo
Tulad ng naaalala mo mula sa Bahagi 1, ang isang pangkat ng pagkuha ay isang pagkakasunud-sunod ng mga character na nakapaloob sa mga panaklong ( ()) metacharacter. Ang layunin ng construct na ito ay iimbak ang mga nahanap na character para magamit muli sa ibang pagkakataon sa panahon ng pagtutugma ng pattern. Ang lahat ng mga character mula sa nakunan na pangkat ay itinuturing bilang isang solong kabuuan sa panahon ng paghahanap ng pattern.
Ang sumusunod na code ay tumatawag sa appendReplacement(StringBuffer sb, String replacement)at mga pamamaraan appendTail(StringBuffer sbupang palitan ang lahat ng paglitaw ng pagkakasunud-sunod ng character sa pinagmulang teksto catng caterpillar:
Pattern p = Pattern.compile("(cat)");
Matcher m = p.matcher("one cat, two cats, or three cats on a fence");
StringBuffer sb = new StringBuffer();
while (m.find())
   m.appendReplacement(sb, "$1erpillar");
m.appendTail(sb);
System.out.println(sb);
Ang paggamit ng isang nakunan na grupo at isang sanggunian dito sa kapalit na teksto ay nagsasabi sa programa na ipasok erpillarpagkatapos ng bawat paglitaw ng cat. Ang resulta ng pagpapatupad ng code na ito ay ganito: one caterpillar, two caterpillars, or three caterpillars on a fence

Pinapalitan ang text

Ang klase Matcheray nagbibigay sa amin ng dalawang paraan para sa pagpapalit ng teksto, pantulong sa appendReplacement(StringBuffer sb, String replacement). Gamit ang mga pamamaraang ito, maaari mong palitan ang alinman sa unang paglitaw ng [pinalitan na teksto] o lahat ng paglitaw:
  • Nire-reset ng pamamaraan String replaceFirst(String replacement)ang matcher, lumilikha ng bagong object String, kinokopya ang lahat ng character ng texter ng matcher (hanggang sa unang tugma) sa string na ito, idinadagdag ang mga character mula sa dulo nito replacement, kinopya ang natitirang mga character sa string at ibinabalik ang isang object String(ang string replacementay maaaring maglaman ng mga sanggunian sa mga nakuha sa nakaraang mga pagkakasunud-sunod ng teksto sa paghahanap gamit ang mga simbolo ng dolyar at mga nakuhang numero ng pangkat).

  • Ang pamamaraan String replaceAll(String replacement)ay gumagana nang katulad sa method String replaceFirst(String replacement), ngunit pinapalitan replacementang lahat ng nahanap na tugma ng mga character mula sa string.

Ang isang regular na expression \s+ay naghahanap ng isa o higit pang mga whitespace na character sa input text. Sa ibaba, gagamitin namin ang regular na expression na ito at tatawag ng paraan replaceAll(String replacement)upang alisin ang mga duplicate na espasyo:
Pattern p = Pattern.compile("\\s+");
Matcher m = p.matcher("Удаляем      \t\t лишние пробелы.   ");
System.out.println(m.replaceAll(" "));
Narito ang mga resulta: Удаляем лишние пробелы. Regular Expressions sa Java, Part 4 Regular Expressions sa Java, Part 5
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION