JavaRush /จาวาบล็อก /Random-TH /พื้นฐานของนิพจน์ทั่วไปใน Java ส่วนที่ 3
articles
ระดับ

พื้นฐานของนิพจน์ทั่วไปใน Java ส่วนที่ 3

เผยแพร่ในกลุ่ม
เรามาศึกษานิพจน์ทั่วไปกันต่อ ในบทความนี้ เราจะดูคลาสอักขระที่กำหนดไว้ล่วงหน้าตลอดจนการหาปริมาณ (การค้นหาลำดับ) พื้นฐานของนิพจน์ทั่วไปใน Java  ส่วนที่ 3 - 1

คลาสตัวละครที่กำหนดไว้ล่วงหน้า

คลาส API Patternประกอบด้วยคลาสอักขระที่กำหนดไว้ล่วงหน้าซึ่งมีทางลัดที่สะดวกสบายไปยังนิพจน์ทั่วไปที่ใช้กันทั่วไป พื้นฐานของนิพจน์ทั่วไปใน Java  ส่วนที่ 3 - 2ในตารางนี้ โครงสร้างในคอลัมน์ด้านซ้ายเป็นการแสดงชวเลขของนิพจน์ในคอลัมน์ด้านขวา ตัวอย่างเช่น\dหมายถึงตัวเลข (0-9) \wหมายถึงอักษรตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็ก ขีดล่าง หรือตัวเลข) ใช้คลาสอักขระที่กำหนดไว้ล่วงหน้าทุกครั้งที่เป็นไปได้ ซึ่งจะทำให้โค้ดของคุณอ่านง่ายขึ้นและแก้ไขข้อผิดพลาด โครงสร้างที่ขึ้นต้นด้วยแบ็กสแลชเรียกว่า Escape หรือ Protected ในบทความก่อนหน้านี้ เราได้พูดคุยเกี่ยวกับการหลีกเลี่ยงอักขระพิเศษด้วยแบ็กสแลชหรือสัญลักษณ์\Qแล้ว\Eใช้เป็นอักขระปกติ หากคุณใช้แบ็กสแลชที่มีอักขระปกติ (ตัวอักษร) คุณจะต้องหลีกแบ็กสแลชเพื่อให้นิพจน์สามารถคอมไพล์ได้
private final String REGEX = "\\d"; // цифра
ในตัวอย่างนี้\dนิพจน์ทั่วไป จำเป็นต้องมีแบ็กสแลชเพิ่มเติมเพื่อให้โปรแกรมคอมไพล์ โปรแกรมทดสอบของเราจะอ่านนิพจน์ทั่วไปจากคอนโซลโดยตรง ดังนั้นจึงไม่จำเป็นต้องมีเครื่องหมายทับเพิ่มเติม ตัวอย่างต่อไปนี้สาธิตการใช้คลาสอักขระที่กำหนดไว้ล่วงหน้า: พื้นฐานของนิพจน์ทั่วไปใน Java  ส่วนที่ 3 - 3พื้นฐานของนิพจน์ทั่วไปใน Java  ส่วนที่ 3 - 4ในสามตัวอย่างแรก นิพจน์ทั่วไปเป็นเพียง " ." (อักขระพิเศษจุด) ซึ่งหมายถึงอักขระใดๆ ดังนั้นการค้นหาจึงสำเร็จทุกกรณี ตัวอย่างอื่นๆ ใช้คลาสอักขระที่กำหนดไว้ล่วงหน้า ความหมายที่เรากล่าวถึงในตารางด้านบน

ปริมาณ

พื้นฐานของนิพจน์ทั่วไปใน Java  ส่วนที่ 3 - 4ปริมาณช่วยให้คุณสามารถระบุจำนวนครั้งของอักขระในสตริงได้ เรามาดูความซับซ้อนของวิธีการทำงานของตัวระบุปริมาณแบบโลภ ขี้เกียจ และโลภมากกันดีกว่า เมื่อมองแวบแรกอาจดูเหมือนว่าปริมาณ X?, X?? และ X?+ ทำงานในลักษณะเดียวกัน: “X มีอยู่เพียงครั้งเดียวหรือไม่มีเลย” มีความแตกต่างเล็กน้อยในการใช้งานตัวระบุปริมาณเหล่านี้ ซึ่งเราจะดูด้านล่าง

การจับคู่ที่มีความยาวเป็นศูนย์

เริ่มจากคนโลภกันก่อน มาเขียนนิพจน์ทั่วไปที่แตกต่างกันสามแบบ: ตัวอักษร "a" ที่มีอักขระพิเศษ ?, * หรือ + มาดูกันว่าเกิดอะไรขึ้นถ้าเราทดสอบนิพจน์ทั่วไปเหล่านี้ในบรรทัดว่าง: พื้นฐานของนิพจน์ทั่วไปใน Java  ส่วนที่ 3 - 5ในตัวอย่างข้างต้น การค้นหาประสบความสำเร็จในสองกรณีแรก เนื่องจากนิพจน์ a? และ a* อนุญาตให้อักขระ a หายไปจากสตริง โปรดทราบว่าดัชนีการเริ่มต้นและการจับคู่ครั้งสุดท้ายจะเหมือนกัน (0) เนื่องจากสตริงอินพุตไม่มีความยาว โปรแกรมจึงไม่พบอะไรเลย :) ในตำแหน่งแรก กรณีนี้เรียกว่าการจับคู่ที่มีความยาวเป็นศูนย์ การจับคู่ดังกล่าวเกิดขึ้นในหลายกรณี: เมื่อบรรทัดอินพุตว่างเปล่า ที่จุดเริ่มต้นของบรรทัดอินพุต หลังอักขระสุดท้ายของบรรทัด หรือระหว่างอักขระในบรรทัด การแข่งขันที่มีความยาวเป็นศูนย์นั้นง่ายต่อการมองเห็น โดยเริ่มต้นและสิ้นสุดที่ตำแหน่งเดียวกัน มาดูตัวอย่างเพิ่มเติมของการจับคู่ที่มีความยาวเป็นศูนย์ มาสำรวจการจับคู่ที่มีความยาวเป็นศูนย์พร้อมตัวอย่างเพิ่มเติมกัน มาเปลี่ยนสตริงอินพุตเป็นอักขระ "a" และสังเกตเอฟเฟกต์ที่น่าสนใจ: พื้นฐานของนิพจน์ทั่วไปใน Java  ตอนที่ 3 - 6ตัวระบุทั้งสามตัวพบอักขระ "a" แต่สองตัวแรกซึ่งอนุญาตให้ไม่มีอักขระพบการจับคู่ที่มีความยาวเป็นศูนย์ที่ตำแหน่ง 1 - หลังอักขระตัวสุดท้ายของสตริง สิ่งนี้เกิดขึ้นเนื่องจากโปรแกรมถือว่าอักขระ "a" เป็นสตริงและ "รัน" ผ่านอักขระนั้นจนกว่าจะไม่มีรายการที่ตรงกันอีกต่อไป โปรแกรมจะหรือไม่พบ "ไม่มีอะไร" ที่ส่วนท้ายของสตริง ทั้งนี้ขึ้นอยู่กับปริมาณที่ใช้ ตอนนี้เรามาเปลี่ยนสตริงอินพุตเป็นลำดับตัวอักษรห้าตัว "a": พื้นฐานของนิพจน์ทั่วไปใน Java  ส่วนที่ 3 - 7นิพจน์ทั่วไป a? ค้นหาการจับคู่ตัวอักษรแต่ละตัวในสตริงแยกกัน นิพจน์ a* ค้นหารายการที่ตรงกันสองรายการ ได้แก่ ลำดับอักขระ "a"' และการจับคู่ที่มีความยาวเป็นศูนย์ที่ตำแหน่ง 5 และสุดท้ายนิพจน์ทั่วไป a+ ค้นหาเฉพาะลำดับของอักขระ "a" โดยไม่พบ "ไม่มีอะไร" :) จะเกิดอะไรขึ้นหากป้อนสตริงที่มีอักขระต่างกันเป็นอินพุต ตัวอย่างเช่น "ababaaaab": พื้นฐานของนิพจน์ทั่วไปใน Java  ส่วนที่ 3 - 8อักขระ "b" อยู่ในตำแหน่ง 1, 3 และ 8 และโปรแกรมค้นหาการจับคู่ที่มีความยาวเป็นศูนย์ที่ตำแหน่งเหล่านี้ นิพจน์ทั่วไป ก? ไม่ใส่ใจกับ "b" แต่เพียงมองหาการมีอยู่ (หรือไม่มี) ของอักขระ "a" หากตัวระบุอนุญาตให้ไม่มี "a" อักขระทั้งหมดในสตริงอื่นที่ไม่ใช่ "a" จะแสดงเป็นการจับคู่ที่มีความยาวเป็นศูนย์ หากต้องการค้นหาลำดับของความยาวที่กำหนด เพียงระบุความยาวในวงเล็บปีกกา: พื้นฐานของนิพจน์ทั่วไปใน Java  ส่วนที่ 3 - 9นิพจน์ทั่วไป a{3} จะค้นหาลำดับของอักขระ "a" สามตัว ไม่พบสิ่งใดในบรรทัดแรกเนื่องจากมีตัว a ไม่เพียงพอในบรรทัด ตัวที่สองประกอบด้วยอักขระ 3 ตัวซึ่งโปรแกรมจะค้นหา การทดสอบครั้งที่สามยังค้นหาการจับคู่ที่จุดเริ่มต้นของสตริงด้วย ทุกอย่างที่อยู่หลังอักขระตัวที่ 3 ไม่ตรงกับนิพจน์ทั่วไป ในโค้ดด้านล่างเป็นไปตามนั้น และจะมีการจับคู่หลายรายการ: พื้นฐานของนิพจน์ทั่วไปใน Java  ส่วนที่ 3 - 10หากต้องการระบุความยาวลำดับขั้นต่ำ ให้ใช้:
Enter your regex: a{3,}
Enter input string to search: aaaaaaaaa
I found the text "aaaaaaaaa" starting at index 0 and ending at index 9.
ในตัวอย่างนี้ โปรแกรมค้นหารายการที่ตรงกันเพียงรายการเดียวเนื่องจากสตริงตรงตามข้อกำหนดความยาวลำดับขั้นต่ำคือ (3) อักขระ "a" สุดท้าย การตั้งค่าความยาวลำดับสูงสุด: พื้นฐานของนิพจน์ทั่วไปใน Java  ตอนที่ 3 - 11ในตัวอย่างนี้ การจับคู่ครั้งแรกสิ้นสุดด้วยอักขระตัวที่หก คู่ที่ 2 มีอักขระตามหลังคู่ที่ 6 เพราะ เป็นไปตามข้อกำหนดความยาวขั้นต่ำ หากสตริงสั้นกว่าหนึ่งอักขระ ก็จะไม่มีการจับคู่ที่สอง

การใช้กลุ่มอักขระและคลาสด้วยตัวระบุปริมาณ

จนถึงจุดนี้ เราได้ทดสอบตัวปริมาณบนสตริงที่มีอักขระเดียวกัน ตัวระบุปริมาณใช้กับอักขระตัวเดียวเท่านั้น ดังนั้นนิพจน์ทั่วไป "abc+" จะจับคู่สตริงที่มี "ab" และ "c" หนึ่งครั้งหรือมากกว่านั้น จะไม่หมายถึง "abc" อย่างน้อยหนึ่งครั้ง แต่ตัวระบุปริมาณสามารถใช้ร่วมกับกลุ่มและคลาสอักขระได้ เช่น [abc]+ (a หรือ b หรือ c หนึ่งครั้งหรือมากกว่า) หรือ (abc)+ (“abc” หนึ่งครั้งหรือมากกว่า) ลองหากลุ่มของตัวละคร (สุนัข) สามครั้งในบรรทัด: พื้นฐานของนิพจน์ทั่วไปใน Java  ตอนที่ 3 - 12ในตัวอย่างแรกโปรแกรมจะค้นหาคู่ที่ตรงกันเพราะว่า ปริมาณจะขยายไปยังกลุ่มอักขระ หากคุณถอดวงเล็บออก ปริมาณ {3} จะใช้กับตัวอักษร "g" เท่านั้น คุณยังสามารถใช้ตัวระบุปริมาณกับคลาสอักขระได้: Основы регулярных выражений в Java. Часть 3 - 13ตัวระบุ {3} ใช้กับคลาสอักขระในวงเล็บในตัวอย่างแรก และตัวอย่างที่สองใช้กับอักขระ "c" เท่านั้น

ความแตกต่างระหว่างตัวระบุปริมาณแบบโลภ ขี้เกียจ และโลภมากเกินไป

มีความแตกต่างเล็กน้อยระหว่างตัวระบุปริมาณที่โลภ ไม่เต็มใจ และแสดงความเป็นเจ้าของ ตัวระบุปริมาณโลภได้รับการตั้งชื่อเพราะพวกเขาพยายามค้นหาการจับคู่ที่ยาวที่สุดเท่าที่จะเป็นไปได้: ก่อนอื่นโปรแกรมจะพยายาม "กิน" สตริงทั้งหมดหากไม่พบการจับคู่อักขระหนึ่งตัวจะถูกละทิ้งและการค้นหาจะถูกทำซ้ำจนกว่าจะพบการจับคู่หรือ ไม่มีอักขระเหลืออยู่อีกต่อไป ในทางกลับกัน คนเกียจคร้านจะเริ่มตั้งแต่ต้นบรรทัด เติมทีละตัวอักษรจนกว่าจะเจอคู่ที่ตรงกัน ในที่สุด การหาปริมาณด้วยความอิจฉาจะสแกนสตริงทั้งหมดเพียงครั้งเดียว โดยไม่ต้องลบอักขระออกเหมือนอย่างละโมบ สำหรับการสาธิต เราจะใช้สตริง xfooxxxxxxfoo Основы регулярных выражений в Java. Часть 3 - 14ตัวอย่างแรกใช้ตัวระบุ .* greedy เพื่อค้นหาอักขระใดๆ ตั้งแต่ 0 ขึ้นไป ตามด้วยอักขระ "f" "o" "o" เนื่องจาก cantifier มีความละโมบ การแข่งขันที่พบจึงมีสตริงทั้งหมด ตัวระบุปริมาณโลภจะไม่พบรายการที่ตรงกันทั้งหมดในสตริงเนื่องจาก ในขั้นตอนแรกหลังจากสแกนทั้งสตริงแล้วจะพบว่าตรงกันและทำงานให้เสร็จ ตัวอย่างที่สองเป็นแบบขี้เกียจและเริ่มจากจุดเริ่มต้นของบรรทัด โดยเพิ่มอักขระทีละอักขระ โปรแกรมเริ่มต้นด้วยการตรวจสอบ "ความว่างเปล่า" แต่เนื่องจาก ลำดับ "foo" ไม่ได้อยู่ที่จุดเริ่มต้นของบรรทัด การค้นหาจะดำเนินต่อไปโดยการเพิ่มอักขระ "x" หลังจากนั้นจะพบคู่แรกระหว่างดัชนี 0 และ 4 การค้นหาจะดำเนินต่อไปจนถึงจุดสิ้นสุดของบรรทัด และคู่ที่ 2 จะพบระหว่างดัชนี 4 ถึง 13 ตัวอย่างที่ 3 ไม่พบความบังเอิญเพราะตัวนับอิจฉา ในกรณีนี้ นิพจน์ทั่วไป .*+ "ate" ทั้งบรรทัด โดยไม่เหลือ "foo" ไว้เลย ใช้อิจฉาปริมาณเมื่อคุณต้องการทิ้งสิ่งที่ไม่จำเป็นในสตริง มันจะมีประสิทธิภาพมากกว่าปริมาณที่เทียบเท่ากัน นั่นคือทั้งหมด! ลิงก์ไปยังแหล่งที่มา: พื้นฐานของนิพจน์ทั่วไปใน Java ส่วนที่ 3
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION