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 klasePattern
at 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
, Matcher
at 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
, Matcher
at PatternSyntaxException
ang 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 klasePattern
ay 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 nilalamanregex
sa isang intermediate na representasyon na nakaimbak sa isang bagongPattern
. Ang pamamaraang ito ay nagbabalik ng isang reference sa isang bagay kung matagumpay, o naghagis ng isang pagbubukodPatternSyntaxException
kung may nakitang di-wastong syntax ng regular na expression. Ang anumang object ng klaseMatcher
na ginamitPattern
o ibinalik mula sa object na ito ay gumagamit ng mga default na setting nito, gaya ng case-sensitive na paghahanap. Bilang halimbawa, ang code snippetPattern p = Pattern.compile("(?m)^\\.");
ay gumagawa ng isang bagayPattern
na 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 bilangPattern compile(String regex)
, ngunit isinasaalang-alangflags
: isang set ng mga bit constant para sa mga bit na flag ng uri ng OR. Ang klasePattern
ay nagdedeklara ng mga constantCANON_EQ, CASE_INSENSITIVE, COMMENTS, DOTALL, LITERAL, MULTILINE, UNICODE_CASE, UNICODE_CHARACTER_CLASS и UNIX_LINES
na maaaring pagsamahin gamit ang bitwise OR (halimbawa,CASE_INSENSITIVE | DOTALL
) at ipinasa bilang argumentoflags
.
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.MULTILINE
at ang nested flag na expression (?m)
ay gumagawa ng parehong 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 isangPattern
.int flags()
ibinabalik ang mga flag ng objectPattern
.
Pattern
, ito ay karaniwang ginagamit para makuha ang object Matcher
para magsagawa ng pattern matching operations. Ang pamamaraan Matcher matcher(Charsequence input)
ay lumilikha ng isang bagay Matcher
na naghahanap ng teksto input
para 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 Matcher
para sa bagay Pattern
na isinangguni ng variable p
.
Isang beses na paghahanap |
---|
Ang paraan ng static boolean matches(String regex, CharSequence input) klase Pattern ay nagbibigay-daan sa iyo upang makatipid sa paglikha ng mga bagay Pattern at Matcher isang beses na paghahanap gamit ang isang template. Ang pamamaraang ito ay nagbabalik ng true kung input ang 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 only ay naglalaman lamang ng mga puwang at maliliit na character. |
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 klasePattern
ay 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 nahahatitext
ayon sa nahanap na mga tugma sa object patternPattern
at 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 satext
.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-1
mga tugma at ang haba ng array ay hindi hihigit salimit
mga 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.
- Ang isang positibong halaga ay naghahanap ng hindi hihigit sa
- Tinatawag ng pamamaraan
String[] split(CharSequence text)
ang nakaraang pamamaraan na may 0 bilang argumentong limitasyon at ibinabalik ang resulta ng tawag nito.
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,Pattern
lumitaw 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 c
at 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 klaseMatcher
ay 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 Matcher
ay 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 saRegexDemo
Bahagi 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 parameterstart
. Kung matagumpay ang paghahanap, ibabalik ang boolean value na true. Halimbawa,m.find(1);
ini-scan ang teksto simula sa posisyon1
(ang posisyon 0 ay binabalewala). Kung ang parameterstart
ay naglalaman ng negatibong value o isang value na mas malaki kaysa sa matcher na haba ng text, ang paraan ay naghahatid ng exceptionjava.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 codefalse
dahil 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 pamamaraanmatches();
, 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 ngtrue
, dahil ang simula ng tekstoabc!
ay binubuo lamang ng mga character na bumubuo ng salita.
Pattern
, ang mga bagay sa klase Matcher
ay 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 objectMatcher
. Halimbawa,m.reset();
ni-reset ang solver na isinangguni ngm
. -
Nire-reset ng pamamaraan
Matcher reset(CharSequence text)
ang estado ng solver at itinatakda ang bagong teksto ng solver satext
. Ang susunod na operasyon ng paghahanap ng pattern ay magsisimula sa simula ng bagong teksto ng matcher. Nagbabalik ng reference sa kasalukuyang objectMatcher
. Halimbawa,m.reset("new text");
nire-reset ang isinangguni na resolverm
at itinatakda ang bagong solver na text sa"new text"
.
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 urijava.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 bagayStringBuffer
na tinutukoy ng argumentosb
. 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 uriString
na isinangguni ng argumentoreplacement
hanggang sa dulo ng objectStringBuffer
(ang stringreplacement
ay 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
StringBuffer appendTail(StringBuffer sb)
ay nagdaragdag ng lahat ng teksto sa isang bagayStringBuffer
at nagbabalik ng isang sanggunian sa bagay na iyon. Pagkatapos ng huling tawag sa pamamaraanappendReplacement(StringBuffer sb, String replacement)
, tawagan ang paraanappendTail(StringBuffer sb)
upang kopyahin ang natitirang teksto sa bagayStringBuffer
.
Ang pamamaraan Matcher appendReplacement(StringBuffer sb, String replacement)
ay nagtatapon ng isang pagbubukod java.lang.IllegalStateException
kung ang tumutugma ay hindi pa nakakahanap ng isang tugma o isang nakaraang pagtatangka sa paghahanap ay nabigo. Naglalagay ito ng pagbubukod IndexOutOfBoundsException
kung ang linya replacement
ay tumutukoy sa isang pangkat ng pagkuha na wala sa pattern).
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. |
appendReplacement(StringBuffer sb, String replacement)
at mga pamamaraan appendTail(StringBuffer sb
upang palitan ang lahat ng paglitaw ng pagkakasunud-sunod ng character sa pinagmulang teksto cat
ng 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 erpillar
pagkatapos 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 klaseMatcher
ay 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 objectString
, kinokopya ang lahat ng character ng texter ng matcher (hanggang sa unang tugma) sa string na ito, idinadagdag ang mga character mula sa dulo nitoreplacement
, kinopya ang natitirang mga character sa string at ibinabalik ang isang objectString
(ang stringreplacement
ay 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 methodString replaceFirst(String replacement)
, ngunit pinapalitanreplacement
ang lahat ng nahanap na tugma ng mga character mula sa string.
\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
GO TO FULL VERSION