นิพจน์ทั่วไป RegEx คืออะไร
อันที่จริงแล้ว นิพจน์ทั่วไป (RegEx ใน Java) เป็นรูปแบบสำหรับการค้นหาสตริงในข้อความ ใน Java การแสดงเริ่มต้นของรูปแบบนี้จะเป็นสตริงเสมอ นั่นคืออ็อบเจ็กต์ของคลาส String อย่างไรก็ตาม ไม่สามารถคอมไพล์สตริงใดๆ ให้เป็นนิพจน์ทั่วไปได้ เฉพาะสตริงที่เป็นไปตามกฎสำหรับการเขียนนิพจน์ทั่วไปเท่านั้น - ไวยากรณ์ที่กำหนดไว้ในข้อกำหนดภาษา ในการเขียนนิพจน์ทั่วไป จะใช้อักขระตัวอักษรและตัวเลข รวมถึงอักขระเมตา - อักขระที่มีความหมายพิเศษในรูปแบบไวยากรณ์ของนิพจน์ทั่วไป ตัวอย่างเช่น:String regex = "java"; // string template "java";
String regex = "\\d{3}"; // string template of three numeric characters;
การสร้างนิพจน์ทั่วไปใน Java
หากต้องการสร้าง RegEx ใน Java คุณต้องปฏิบัติตามสองขั้นตอนง่ายๆ:- เขียนเป็นสตริงโดยใช้ไวยากรณ์นิพจน์ทั่วไป
- รวบรวมสตริงนี้เป็นนิพจน์ทั่วไป
Pattern
การทำงานกับนิพจน์ทั่วไปในโปรแกรม Java เริ่ม ต้นด้วยการสร้างคลาสอ็อบเจ็กต์ compile
เมื่อต้องการทำเช่นนี้ คุณจะต้องเรียกหนึ่งในสอง วิธีแบบคงที่ที่มีอยู่ในคลาส วิธีแรกใช้หนึ่งอาร์กิวเมนต์ - สตริงลิเทอรัลของนิพจน์ทั่วไป และวิธีที่สอง - บวกกับพารามิเตอร์อื่นที่เปิดโหมดสำหรับการเปรียบเทียบเทมเพลตกับข้อความ:
public static Pattern compile (String literal)
public static Pattern compile (String literal, int flags)
รายการค่าพารามิเตอร์ที่เป็นไปได้flags
ถูกกำหนดไว้ในคลาสPattern
และพร้อมให้เราใช้งานเป็นตัวแปรคลาสคงที่ ตัวอย่างเช่น:
Pattern pattern = Pattern.compile("java", Pattern.CASE_INSENSITIVE);//searching for matches with the pattern will be done case-insensitively.
โดยพื้นฐานแล้วคลาสPattern
คือตัวสร้างนิพจน์ทั่วไป ภายใต้ประทุน วิธีcompile
การเรียกตัวสร้างส่วนตัวของคลาสPattern
เพื่อสร้างมุมมองที่คอมไพล์ วิธีการสร้างอินสแตนซ์เทมเพลตนี้ถูกนำมาใช้โดยมีเป้าหมายในการสร้างเป็นออบเจ็กต์ที่ไม่เปลี่ยนรูป เมื่อสร้าง จะมีการตรวจสอบไวยากรณ์ของนิพจน์ทั่วไป หากมีข้อผิดพลาดในบรรทัด ระบบจะสร้างข้อยกเว้นPatternSyntaxException
ขึ้น
ไวยากรณ์นิพจน์ทั่วไป
ไวยากรณ์ของนิพจน์ทั่วไปขึ้นอยู่กับการใช้สัญลักษณ์<([{\^-=$!|]})?*+.>
ซึ่งสามารถใช้ร่วมกับอักขระตัวอักษรได้ ขึ้นอยู่กับบทบาทของพวกเขา พวกเขาสามารถแบ่งออกเป็นหลายกลุ่ม:
เมตาคาแรคเตอร์ | วัตถุประสงค์ |
---|---|
^ | จุดเริ่มต้นของบรรทัด |
$ | สิ้นสุดบรรทัด |
\ข | ขอบเขตคำ |
\บี | ไม่ใช่การจำกัดคำ |
\ก | จุดเริ่มต้นของการป้อนข้อมูล |
\จี | จบการแข่งขันครั้งก่อน |
\Z | สิ้นสุดการป้อนข้อมูล |
\z | สิ้นสุดการป้อนข้อมูล |
เมตาคาแรคเตอร์ | วัตถุประสงค์ |
---|---|
\d | สัญลักษณ์ดิจิทัล |
\D | อักขระที่ไม่ใช่ตัวเลข |
\s | อักขระอวกาศ |
\ส | อักขระที่ไม่ใช่ช่องว่าง |
\w | อักขระตัวอักษรและตัวเลขหรือขีดล่าง |
\ว | อักขระใดๆ ที่ไม่ใช่ตัวอักษร ตัวเลข หรือขีดล่าง |
. | ตัวละครใดก็ได้ |
เมตาคาแรคเตอร์ | วัตถุประสงค์ |
---|---|
\t | อักขระแท็บ |
\n | อักขระขึ้นบรรทัดใหม่ |
\r | อักขระการคืนรถ |
\ฉ | ไปที่หน้าใหม่ |
\u0085 | อักขระบรรทัดถัดไป |
\u2028 | อักขระตัวคั่นบรรทัด |
\u2029 | สัญลักษณ์ตัวคั่นย่อหน้า |
เมตาคาแรคเตอร์ | วัตถุประสงค์ |
---|---|
[ก ค ค] | ข้อใดข้อหนึ่งข้างต้น (a, b หรือ c) |
[^เอบีซี] | นอกเหนือจากที่ระบุไว้ (ไม่ใช่ a, b, c) |
[a-zA-Z] | การรวมช่วง (อักขระละติน a ถึง z ไม่คำนึงถึงขนาดตัวพิมพ์) |
[โฆษณา[mp]] | การต่ออักขระ (a ถึง d และ m ถึง p) |
[az&&[def]] | จุดตัดของสัญลักษณ์ (สัญลักษณ์ d,e,f) |
[az&&[^bc]] | การลบอักขระ (อักขระ a, dz) |
เมตาคาแรคเตอร์ | วัตถุประสงค์ |
---|---|
? | หนึ่งหรือขาดหายไป |
* | ศูนย์หรือมากกว่าครั้ง |
+ | หนึ่งครั้งหรือมากกว่านั้น |
{n} | n ครั้ง |
{n,} | n ครั้งหรือมากกว่า |
{n,m} | ไม่น้อยกว่า n ครั้ง และไม่เกิน m ครั้ง |
โหมดปริมาณโลภ
คุณสมบัติพิเศษของตัวระบุปริมาณคือความสามารถในการใช้ในโหมดต่างๆ: โลภ โลภมาก และขี้เกียจ โหมดโลภพิเศษจะเปิดขึ้นโดยการเพิ่มสัญลักษณ์ “+
” หลังตัวปริมาณ และโหมดขี้เกียจโดยการเพิ่มสัญลักษณ์ “ ?
“ ตัวอย่างเช่น:
"A.+a" // greedy mode
"A.++a" // over-greedy mode
"A.+?a" // lazy mode
ใช้เทมเพลตนี้เป็นตัวอย่าง เราจะมาพยายามทำความเข้าใจว่าตัวระบุทำงานอย่างไรในโหมดต่างๆ ตามค่าเริ่มต้น ตัวปริมาณจะทำงานในโหมดโลภ ซึ่งหมายความว่าจะค้นหาการจับคู่ที่ยาวที่สุดเท่าที่จะเป็นไปได้ในสตริง จากการรันโค้ดนี้:
public static void main(String[] args) {
String text = "Egor Alla Alexander";
Pattern pattern = Pattern.compile("A.+a");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println(text.substring(matcher.start(), matcher.end()));
}
}
เราจะได้ผลลัพธ์ต่อไปนี้: Alla Alexa อัลกอริธึมการค้นหาสำหรับรูปแบบที่กำหนด " А.+а
" ดำเนินการตามลำดับต่อไปนี้:
-
ในรูปแบบที่กำหนด อักขระตัวแรกคืออักขระตัวอักษร
А
รัสเซียMatcher
จับคู่กับอักขระทุกตัวในข้อความ โดยเริ่มต้นที่ตำแหน่งศูนย์ ที่ตำแหน่งศูนย์ในข้อความของเราจะมีสัญลักษณ์Е
ดังนั้นMatcher
จึงต้องผ่านอักขระในข้อความตามลำดับจนกว่าจะตรงกับรูปแบบ ในตัวอย่างของเรา นี่คือสัญลักษณ์ที่ตำแหน่งหมายเลข 5 -
หลังจากพบการจับคู่กับอักขระตัวแรกของรูปแบบแล้ว
Matcher
ระบบจะตรวจสอบการจับคู่กับอักขระตัวที่สองของรูปแบบ ในกรณีของเรา นี่คือสัญลักษณ์ “.
” ซึ่งหมายถึงอักขระใดๆตำแหน่งที่ 6 เป็นสัญลักษณ์ตัว
л
อักษร แน่นอนว่ามันตรงกับรูปแบบ "อักขระใดๆ" -
Matcher
ไปยังการตรวจสอบอักขระถัดไปจากรูปแบบ ในเทมเพลตของเรา มีการระบุโดยใช้.+
ตัวปริมาณ “ ” เนื่องจากจำนวนการซ้ำของ “อักขระใดๆ” ในรูปแบบคือหนึ่งครั้งหรือมากกว่านั้นMatcher
อักขระตัวถัดไปจากสตริงจะสลับกันและตรวจสอบความสอดคล้องกับรูปแบบ ตราบใดที่ตรงตามเงื่อนไข “อักขระใดๆ” ในตัวอย่างของเรา - จนถึงจุดสิ้นสุดของบรรทัด ( จากตำแหน่งหมายเลข 7 - หมายเลข 18 ของข้อความ).ในความเป็นจริง
Matcher
มันจับทั้งบรรทัดจนถึงจุดสิ้นสุด - นี่คือจุดที่ "ความโลภ" ของมันแสดงออกมา -
หลังจาก
Matcher
ไปถึงจุดสิ้นสุดของข้อความและตรวจสอบА.+
ส่วน " " ของรูปแบบเสร็จแล้ว Matcher จะเริ่มตรวจสอบส่วนที่เหลือของรูปแบบ - อักขระตัวа
อักษร เนื่องจากข้อความในทิศทางไปข้างหน้าสิ้นสุดลง การตรวจสอบจึงเกิดขึ้นในทิศทางย้อนกลับ โดยเริ่มจากอักขระตัวสุดท้าย: -
Matcher
"จำ" จำนวนการทำซ้ำในรูปแบบ ".+
" ซึ่งถึงจุดสิ้นสุดของข้อความ จึงลดจำนวนการทำซ้ำลงหนึ่งรายการและตรวจสอบรูปแบบของข้อความจนกว่าจะพบรายการที่ตรงกัน:
โหมดปริมาณที่โลภมาก
ในโหมดโลภมาก ตัวจับคู่จะทำงานคล้ายกับกลไกของโหมดโลภมาก ข้อแตกต่างคือเมื่อคุณจับข้อความที่ท้ายบรรทัด จะไม่มีการค้นหาย้อนหลัง นั่นคือสามขั้นตอนแรกในโหมดโลภมากจะคล้ายกับโหมดโลภมาก หลังจากจับสตริงทั้งหมดแล้ว เครื่องมือจับคู่จะเพิ่มรูปแบบที่เหลือและเปรียบเทียบกับสตริงที่จับได้ ในตัวอย่างของเรา เมื่อดำเนินการวิธีการหลักด้วยรูปแบบ "А.++а
" จะไม่พบรายการที่ตรงกัน
โหมดปริมาณขี้เกียจ
-
ในโหมดนี้ ในระยะเริ่มแรก เช่นเดียวกับในโหมดโลภ การจับคู่จะถูกค้นหาด้วยอักขระตัวแรกของรูปแบบ:
-
ถัดไป จะค้นหาการจับคู่กับอักขระถัดไปในรูปแบบ - อักขระใดๆ:
-
ต่างจากโหมดโลภ โหมดขี้เกียจจะค้นหาการจับคู่ที่สั้นที่สุดในข้อความ ดังนั้นหลังจากค้นหาการจับคู่กับอักขระตัวที่สองของรูปแบบ ซึ่งระบุด้วยจุดและจับคู่อักขระที่ตำแหน่งหมายเลข 6 ของข้อความ
Matcher
จะตรวจสอบว่าข้อความตรงกับส่วนที่เหลือของรูปแบบหรือไม่ - อักขระ "а
" -
เนื่องจากไม่พบการจับคู่กับรูปแบบในข้อความ (ที่ตำแหน่งหมายเลข 7 ในข้อความมีสัญลักษณ์ " "
л
)Matcher
จึงเพิ่ม "อักขระใด ๆ " อีกหนึ่งตัวในรูปแบบเนื่องจากมีการระบุเป็นหนึ่งครั้งหรือมากกว่านั้น และเปรียบเทียบรูปแบบกับข้อความในตำแหน่งหมายเลข 5 กับหมายเลข 8 อีกครั้ง: -
ในกรณีของเราพบรายการที่ตรงกัน แต่ยังไม่ถึงจุดสิ้นสุดของข้อความ ดังนั้นจากตำแหน่งที่ 9 การตรวจสอบจึงเริ่มต้นด้วยการค้นหาอักขระตัวแรกของรูปแบบโดยใช้อัลกอริธึมที่คล้ายกันแล้วทำซ้ำจนกระทั่งสิ้นสุดข้อความ
main
เมื่อใช้А.+?а
เทมเพลต " " เราจะได้ผลลัพธ์ดังต่อไปนี้: Alla Alexa ดังที่เห็นได้จากตัวอย่างของเรา เมื่อใช้โหมดปริมาณที่แตกต่างกันสำหรับเทมเพลตเดียวกัน เราก็ได้ผลลัพธ์ที่แตกต่างกัน ดังนั้นจึงจำเป็นต้องคำนึงถึงคุณสมบัตินี้และเลือกโหมดที่ต้องการขึ้นอยู่กับผลลัพธ์ที่ต้องการระหว่างการค้นหา
การหลีกอักขระในนิพจน์ทั่วไป
เนื่องจากนิพจน์ทั่วไปใน Java หรือการแสดงเริ่มต้นอย่างแม่นยำยิ่งขึ้น ได้รับการระบุโดยใช้ตัวอักษรสตริง จึงจำเป็นต้องคำนึงถึงกฎของข้อกำหนดเฉพาะ Java ที่เกี่ยวข้องกับตัวอักษรสตริง โดยเฉพาะอย่างยิ่ง อักขระแบ็กสแลช "\
" ในตัวอักษรสตริงในซอร์สโค้ด Java จะถูกตีความว่าเป็นอักขระหลีกที่แจ้งเตือนคอมไพลเลอร์ว่าอักขระที่ตามหลังอักขระนั้นเป็นอักขระพิเศษและต้องถูกตีความด้วยวิธีพิเศษ ตัวอย่างเช่น:
String s = "The root directory is \nWindows";//wrap Windows to a new line
String s = "The root directory is \u00A7Windows";//insert paragraph character before Windows
ดังนั้นในตัวอักษรสตริงที่อธิบายนิพจน์ทั่วไปและใช้\
อักขระ " " (เช่น สำหรับอักขระเมตา) จะต้องเพิ่มเป็นสองเท่าเพื่อให้คอมไพเลอร์ Java bytecode ไม่ตีความแตกต่างออกไป ตัวอย่างเช่น:
String regex = "\\s"; // template for searching for space characters
String regex = "\"Windows\""; // pattern to search for the string "Windows"
ควรใช้อักขระแบ็กสแลชคู่เพื่อหลีกอักขระพิเศษ หากเราวางแผนที่จะใช้เป็นอักขระ "ปกติ" ตัวอย่างเช่น:
String regex = "How\\?"; // template for searching the string "How?"
วิธีการเรียนรูปแบบ
คลาสPattern
มีวิธีการอื่นสำหรับการทำงานกับนิพจน์ทั่วไป: String pattern()
– ส่งคืนการแสดงสตริงดั้งเดิมของนิพจน์ทั่วไปที่ใช้สร้างอ็อบเจ็กต์Pattern
:
Pattern pattern = Pattern.compile("abc");
System.out.println(Pattern.pattern())//"abc"
static boolean matches(String regex, CharSequence input)
– ให้คุณตรวจสอบนิพจน์ทั่วไปที่ส่งในพารามิเตอร์ regex กับข้อความที่ส่งในinput
พารามิเตอร์ ส่งคืน: จริง – หากข้อความตรงกับรูปแบบ เท็จ – มิฉะนั้น; ตัวอย่าง:
System.out.println(Pattern.matches("A.+a","Alla"));//true
System.out.println(Pattern.matches("A.+a","Egor Alla Alexander"));//false
int flags()
– ส่งคืนflags
ค่าพารามิเตอร์เทมเพลตที่ตั้งค่าไว้เมื่อสร้างขึ้น หรือ 0 หากไม่ได้ตั้งค่าพารามิเตอร์นี้ ตัวอย่าง:
Pattern pattern = Pattern.compile("abc");
System.out.println(pattern.flags());// 0
Pattern pattern = Pattern.compile("abc",Pattern.CASE_INSENSITIVE);
System.out.println(pattern.flags());// 2
String[] split(CharSequence text, int limit)
– แยกข้อความที่ส่งเป็นพารามิเตอร์ออกเป็นอาร์เรย์ของString
องค์ประกอบ พารามิเตอร์limit
กำหนดจำนวนการแข่งขันสูงสุดที่จะค้นหาในข้อความ:
- เมื่อ
limit>0
– ทำการค้นหาlimit-1
การแข่งขัน; - ที่
limit<0
- ค้นหารายการที่ตรงกันทั้งหมดในข้อความ - เมื่อ
limit=0
– ค้นหารายการที่ตรงกันทั้งหมดในข้อความ ในขณะที่บรรทัดว่างที่ส่วนท้ายของอาร์เรย์จะถูกละทิ้ง
public static void main(String[] args) {
String text = "Egor Alla Anna";
Pattern pattern = Pattern.compile("\\s");
String[] strings = pattern.split(text,2);
for (String s : strings) {
System.out.println(s);
}
System.out.println("---------");
String[] strings1 = pattern.split(text);
for (String s : strings1) {
System.out.println(s);
}
}
เอาต์พุตคอนโซล: Egor Alla Anna -------- Egor Alla Anna เราจะพิจารณา วิธีคลาสอื่นสำหรับการสร้างวัตถุMatcher
ด้านล่าง
วิธีการคลาส Matcher
Matcher
เป็นคลาสที่ใช้สร้างวัตถุเพื่อค้นหารูปแบบ Matcher
– นี่คือ "เครื่องมือค้นหา" ซึ่งเป็น "เครื่องมือ" ของนิพจน์ทั่วไป ในการค้นหา เขาจะต้องได้รับสองสิ่ง: รูปแบบการค้นหา และ "ที่อยู่" ที่จะค้นหา ในการสร้างวัตถุMatcher
วิธีการต่อไปนี้มีให้ในชั้นเรียนPattern
: рublic Matcher matcher(CharSequence input)
ในฐานะที่เป็นอาร์กิวเมนต์ วิธีการจะใช้ลำดับของอักขระที่จะดำเนินการค้นหา เหล่านี้เป็นวัตถุของคลาสที่ใช้อินเทอร์เฟCharSequence
ซ String
คุณสามารถส่งผ่านไม่เพียง แต่ แต่ยังส่งStringBuffer
ผ่านเป็นอาร์กิวเมนต์ได้StringBuilder
ด้วย เทมเพลตการค้นหาคือคลาสอ็อบเจ็กต์ที่เรียกว่าเมธอด ตัวอย่างการสร้างตัวจับคู่: Segment
CharBuffer
Pattern
matcher
Pattern p = Pattern.compile("a*b");// compiled the regular expression into a view
Matcher m = p.matcher("aaaaab");//created a search engine in the text “aaaaab” using the pattern "a*b"
ขณะนี้ ด้วยความช่วยเหลือของ "เครื่องมือค้นหา" ของเรา เราสามารถค้นหารายการที่ตรงกัน ค้นหาตำแหน่งของรายการที่ตรงกันในข้อความ และแทนที่ข้อความโดยใช้วิธีการเรียน วิธีการboolean find()
ค้นหาการจับคู่ถัดไปในข้อความด้วยรูปแบบ เมื่อใช้วิธีการนี้และตัวดำเนินการวนซ้ำ คุณสามารถวิเคราะห์ข้อความทั้งหมดตามโมเดลเหตุการณ์ (ดำเนินการที่จำเป็นเมื่อมีเหตุการณ์เกิดขึ้น - ค้นหารายการที่ตรงกันในข้อความ) ตัวอย่างเช่น เมื่อใช้วิธีการของคลาสนี้int start()
คุณint end()
สามารถกำหนดตำแหน่งของรายการที่ตรงกันในข้อความ และใช้เมธอดString replaceFirst(String replacement)
เพื่อString replaceAll(String replacement)
แทนที่รายการที่ตรงกันในข้อความด้วยข้อความแทนที่อื่น ตัวอย่าง:
public static void main(String[] args) {
String text = "Egor Alla Anna";
Pattern pattern = Pattern.compile("A.+?a");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
int start=matcher.start();
int end=matcher.end();
System.out.println("Match found" + text.substring(start,end) + " с "+ start + " By " + (end-1) + "position");
}
System.out.println(matcher.replaceFirst("Ira"));
System.out.println(matcher.replaceAll("Olga"));
System.out.println(text);
}
ผลลัพธ์ของโปรแกรม: พบการแข่งขัน Alla จาก 5 ถึง 8 ตำแหน่ง พบการแข่งขัน Anna จาก 10 ถึง 13 ตำแหน่ง Egor Ira Anna Egor Olga Olga Egor Alla Anna จากตัวอย่างเป็นที่ชัดเจนว่าวิธีreplaceFirst
การสร้างreplaceAll
วัตถุใหม่String
- สตริงซึ่ง คือข้อความต้นฉบับที่ตรงกับเทมเพลตจะถูกแทนที่ด้วยข้อความที่ส่งไปยังเมธอดเป็นอาร์กิวเมนต์ นอกจากนี้ วิธีการนี้replaceFirst
จะแทนที่เฉพาะนัดแรกและreplaceAll
ทุกนัดในการทดสอบ ข้อความต้นฉบับยังคงไม่เปลี่ยนแปลง การใช้วิธีคลาสอื่นMatcher
เช่นเดียวกับตัวอย่างของนิพจน์ทั่วไป สามารถพบได้ในบทความ ชุด นี้ การดำเนินการที่พบบ่อยที่สุดกับนิพจน์ทั่วไปเมื่อทำงานกับข้อความนั้นมาจากคลาสPattern
และMatcher
ถูกสร้างไว้ในไฟล์String
. เหล่านี้เป็นวิธีการเช่นsplit
, matches
, replaceFirst
, replaceAll
. แต่ในความเป็นจริง "ภายใต้ประทุน" พวกเขาใช้Pattern
และMatcher
. ดังนั้น หากคุณต้องการแทนที่ข้อความหรือเปรียบเทียบสตริงในโปรแกรมโดยไม่ต้องเขียนโค้ดที่ไม่จำเป็น ให้ใช้เมธอดของString
. หากคุณต้องการความสามารถขั้นสูง ลองนึกถึงคลาสPattern
และMatcher
.
บทสรุป
นิพจน์ทั่วไปอธิบายไว้ในโปรแกรม Java โดยใช้สตริงที่ตรงกับรูปแบบที่กำหนดโดยกฎ เมื่อโค้ดทำงาน Java จะคอมไพล์สตริงนี้ใหม่ลงในคลาสอ็อบเจ็กต์Pattern
และใช้คลาสอ็อบเจ็กต์Matcher
เพื่อค้นหารายการที่ตรงกันในข้อความ ดังที่ผมได้กล่าวไปแล้วในตอนต้น สำนวนปกติมักถูกละไว้เพื่อใช้ในภายหลัง ซึ่งถือเป็นหัวข้อที่ยาก อย่างไรก็ตาม หากคุณเข้าใจพื้นฐานของไวยากรณ์ เมตาคาแรคเตอร์ การ Escape และศึกษาตัวอย่างของนิพจน์ทั่วไป สิ่งเหล่านี้จะง่ายกว่าที่เห็นเมื่อมองแวบแรกมาก
GO TO FULL VERSION