การวิเคราะห์ตัวหนังสือหรือข้อความเป็นงานอย่างหนึ่งที่สามารถทำได้โดยอาศัยการเขียนโปรแกรมเพื่อช่วยจัดการ
ในการเขียนโปรแกรมวิเคราะห์ข้อความนั้น
มีเทคนิคหนึ่งที่ควรจะรู้เพราะเป็นประโยชน์เป็นอย่างมากนั่นคือสิ่งที่เรียกว่า
เรกูลาร์ เอ็กซ์เพรชชัน (regular expression)
เนื่องจากชื่อยาวจึงมักจะถูกเรียกย่อๆว่า regex หรือบางทีก็สั้นๆเป็น re
และในภาษาไทยบางครั้งก็อาจแปลว่า "นิพจน์ปกติ"
ต่อจากนี้ไปในบทความนี้จะเรียกสั้นๆว่า regex
ภาษาโปรแกรมต่างๆส่วนใหญ่ได้บรรจุคำสั่งสำหรับใช้งาน regex เอาไว้
แม้แต่ละภาษาจะมีไวยากรณ์ที่แตกต่างกัน แต่รูปแบบของ regex
นั้นโดยรวมๆแล้วมีลักษณะเหมือนกัน แม้จะมีความแตกต่างในรายละเอียดปลีกย่อย
นอกจากเวลาเขียนโปรแกรมแล้ว ในพวกโปรแกรมแก้ไขข้อความ เช่น atom หรือ vscode
พวกนี้ก็สามารถค้นหาโดยใช้ regex เช่นกัน จึงมีประโยชน์ที่จะเรียนรู้
ใช้งานได้กว้างขวาง
ในบทความนี้จะอธิบายการใช้ regex แบบทั่วไป
โดยไม่พูดถึงวิธีการใช้ที่จำเพาะในภาษาต่างๆ
เพื่อที่ว่าไม่ว่าใครใช้ภาษาอะไรอยู่ก็สามารถอ่านบทความนี้เพื่อเรียนรู้ regex
ได้เหมือนกัน
เพียงแต่ว่าผลของ regex
บางส่วนอาจมีการแสดงผลแตกต่างไปในแต่ละภาษาอย่างหลีกเลี่ยงไม่ได้
หากส่วนไหนสำคัญก็จะเน้นย้ำเป็นพิเศษให้รู้
โดยในที่นี้จะเน้นผลที่ปรากฏในภาษา
จาวาสคริปต์ (javascript),
ไพธอน (python),
รูบี (ruby) และ
php
หากตรงไหนไม่ได้เขียนเน้นว่าเป็นผลในภาษาไหนหมายความว่าใช้ได้เหมือนกันทุกภาษา
(อย่างน้อยก็ใน ๔ ภาษาที่ยกมานี้ แต่ภาษาอื่นก็อาจมีอะไรต่างไปอีกได้)
แต่ตรงไหนที่ต่างจะอธิบายแยกไว้
จุดประสงค์ในการใช้ regex
ก่อนอื่นต้องมาทำความเข้าใจกันให้ดีก่อนว่า regex คืออะไร
ขอยกตัวอย่างง่ายๆว่า สมมุติเรามีข้อความ (สายอักขระ)
ยาวๆอันนึงแบบนี้ที่มีทั้งตัวเลขและตัวอักษรปนกัน
หากต้องการค้นเอาเฉพาะส่วนที่เป็นตัวเลขอย่างเดียว
หรือตัวหนังสืออย่างเดียวจะทำอย่างไร?
เวลาใช้พวกโปรแกรมแก้ไขข้อความ หรือแม้แต่ในเว็บเราสามารถกดค้นคำได้
แต่ปกติจะแค่พิมพ์อักษรที่ต้องการค้น เช่นต้องการหาเลข 1 ก็พิมพ์ 1 ต้องการหาเลข
9 ก็พิมพ์เลข 9 แต่ถ้าหากต้องการหาเลขตั้งแต่ 0 ถึง 9
พร้อมกันทีเดียวจะทำอย่างไร?
ตรงนี้เองคือสิ่งที่สามารถใช้ประโยชน์จาก regex ได้
งานนี้หากใช้ regex
ก็สามารถค้นหาเฉพาะตัวหนังสือที่ต้องการออกมาจากตัวหนังสือยาวๆได้โดยแค่พิมพ์โค้ดสำหรับค้นลงไป
ต่อไปมาดูวิธีการ
ตัวทดลองใช้ regex
เพื่อให้สะดวกที่จะเรียนรู้ เราได้เตรียมที่สำหรับทดสอบ regex เอาไว้ในบล็อกนี้
สามารถไปลองทดสอบใช้กันได้
>>
https://phyblas.hinaboshi.com/regex
ในการใช้งานให้ใส่คำค้น regex ที่ช่องด้านบน แล้วใส่ข้อความที่ช่องด้านล่าง
จากนั้นผลลัพธ์การค้นจะแสดงขึ้นทางฝั่งขวา
ส่วนโหมดและตัวเลือกเสริมนั้นเดี๋ยวจะอธิบายทีหลัง
ตอนนี้ถ้าไม่ได้กล่าวถึงเป็นพิเศษให้ถือว่าไม่ได้ติ๊กตัวเลือกเสริมอะไร
ส่วนโหมดเป็นค้นหาธรรมดา
โค้ดนี้ถูกเขียนด้วยจาวาสคริปต์
ดังนั้นหมายความว่าผลการค้นหาจะเป็นของจาวาสคริปต์เท่านั้น
แต่ที่ยกตัวอย่างต่อไปนี้จะมีบางส่วนที่ใช้ในจาวาคริปต์ไม่ได้อยู่ด้วย
(ซึ่งจะมีบอกไว้ชัด) จึงไม่สามารถทดสอบตามในนี้ได้ แต่ถ้าใครสามารถรัน regex
ในไพธอนหรือรูบีได้ก็ลองทดสอบดู จะเห็นผลตามนั้นได้
การค้นหาคัดกรองตัวเลขออกจากตัวหนังสืออื่นๆ (ใช้ \d และ \D)
เริ่มแรกเปิดหน้าตัวทดสอบ regex ขึ้นมา
ลองใส่ตัวหนังสือยุ่งๆเมื่อครู่นี้ลงในช่องข้อความ แล้วลองใส่อักษร \d
ในช่องคำค้น
ผลที่ได้ก็จะออกมาเป็นแบบนี้
คำค้น |
ข้อความ | ผลการค้น d7fjk38fbk84 s84kkc8|8slsy4ub5cjo 1293a8a1lp9 |
กลุ่มคำที่เข้าข่าย 888888 |
จะเห็นว่าเลข 8 ถูกไฮไลต์ทั้งหมด และแต่ละตัวก็แสดงให้เห็นตรงด้านล่างด้วย
ข้อความค้นก็คือตัวที่เราต้องการค้นนั่นเอง แต่ว่าใส่แค่เลข 8
ไปง่ายๆแบบนี้มันก็จะค้นเจอแต่เลข 8 ดูเหมือนพิมพ์ข้อความค้นธรรมดา
ไม่มีอะไรเป็นพิเศษ ยังไม่ได้ใช้ประโยชน์จาก regex
ทีนี้ลองเปลี่ยนเป็นพิมพ์ \d ลงไปดู
คำค้น |
ข้อความ | ผลการค้น d7fjk3|8fbk8|4 s8|4kkc8|8slsy4ub5cjo 1|2|9|3a8a1lp9 |
กลุ่มคำที่เข้าข่าย 738848488451293819 |
จะพบว่าที่เป็นตัวเลขทั้งหมดถูกเลือกและแสดงไว้ที่ด้านล่างทั้งหมด
ในการใช้ regex นั้น \d เป็นโค้ดที่เอาไว้แทนตัวเลขใดๆก็ได้ตั้งแต่ 0 ถึง 9
ดังนั้นแค่พิมพ์ \d ลงในช่องค้นจึงเป็นการหาตัวเลขใดๆก็ได้ทั้งหมดในทีเดียว
และถ้าพิมพ์ \d ไป ๒ ตัวจะเป็นการค้นตัวเลขที่อยู่ติดกัน ๒ ตัว
คำค้น |
ข้อความ | ผลการค้น d7fjk38fbk84 s84kkc88slsy4ub5cjo 12|93a8a1lp9 |
กลุ่มคำที่เข้าข่าย 388484881293 |
ในทางตรงกันข้าม มี \D ซึ่งมีความหมายตรงกันข้ามกับ \d
คือแทนอะไรก็ตามที่ไม่ใช่ตัวเลข
ลองใช้ \D ค้นดู
คำค้น |
ข้อความ | ผลการค้น d7fjk38fbk84 s84kkc88sl|sy4ub5cj|o 1293a8a1lp9 |
กลุ่มคำที่เข้าข่าย fjfb skkslsyubcjo lp |
คราวนี้จะได้แต่เฉพาะที่ไม่ใช่ตัวเลขแทน
หรือถ้าต้องการหาที่เป็นตัวเลขแล้วตามด้วยที่ไม่ใช่ตัวเลขก็ใส่ \d\D แบบนี้
คำค้น |
ข้อความ | ผลการค้น d7fjk38fbk84 s84kkc88slsy4ub5cjo 1293a|8a|1lp9 |
กลุ่มคำที่เข้าข่าย 7f8f4 4k8s4u5c3a8a1l |
สัญลักษณ์แทนตัวอักษรชนิดต่างๆ (เช่น \w, \W, \s, \S, ., ฯลฯ)
นอกจาก \d ซึ่งแทนตัวเลข และ \D
ที่แทนสิ่งอื่นนอกจากตัวเลขแล้วยังมีรูปแบบอื่นๆอีกมากมายซึ่งก็มักเขียนแทนด้วยแบ็กสแลช
(\) แบบนี้ มีดังนี้
\d | ตัวเลข 0-9 |
\D | ตัวอื่นนอกจากตัวเลข 0-9 |
\t | แท็บ |
\n | ขึ้นบรรทัดใหม่ |
\s | สเปซบาร์หรือแท็บหรือขึ้นบรรทัดใหม่ |
\S | ตัวอื่นนอกจากสเปซบาร์หรือแท็บหรือขึ้นบรรทัดใหม่ |
\w | ตัวเลขและอักษร รวมถึงขีดล่าง (_) |
\W | ตัวอื่นที่ไม่ใช่ \w |
. (จุด) | แทนตัวอักษรอะไรก็ได้ |
จะเห็นว่ามีการแยกตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก โดยที่ตัวพิมพ์ใหญ่เช่น \D \S \W
จะมีความหมายตรงกันข้ามกับตัวพิมพ์เล็ก \d \s \w ต้องแยกใช้ให้ดี
สำหรับ \w นั้นมีข้อควรระวัง คือผลที่ได้จะต่างกันไปโดยในจาวาสคริปต์และรูบี \w
จะแทนแค่ตัวอักษรภาษาอังกฤษและตัวเลขและ _
แต่ในไพธอนจะรวมทั้งตัวอักษรภาษาอื่นๆด้วย
ตัวอย่างเช่นลองค้นด้วย \w
ในจาวาสคริปต์, รูบี และ php จะเป็นแบบนี้
คำค้น |
ข้อความ | ผลการค้น (ใน javascript, ruby, php) 555 !!! ฮาฮาฮา hah|aha ๕๕๕ ははは 하하하 哈哈哈 ?&^ H-H_H- |
กลุ่มคำที่เข้าข่าย 555hahahaH_H |
แต่ถ้าค้นในไพธอนจะได้ผลแบบนี้
คำค้น |
ข้อความ | ผลการค้น (ใน python) 555 !!! ฮาฮ|าฮา hah|aha ๕๕๕ ははは 하하하 哈哈哈 ?&^ H-H_H- |
กลุ่มคำที่เข้าข่าย 555ฮาฮาฮาhahaha๕๕๕ははは하하하哈哈哈H_H |
การที่ผลลัพธ์ต่างกันแบบนี้ ทำให้การใช้ \w
ในการค้นอาจต้องระวังเป็นพิเศษ
ส่วน \W
นั้นก็จะเป็นตัวที่ตรงกันข้ามกับ \w ดังนั้นจึงมีความหมายเปลี่ยนไปด้วยเช่นกัน
ส่วน \s จะแทนตัวอักษรเว้นวรรคหนึ่งตัว นั่นคือสเปซบาร์ (" ", คือช่องว่าง)
และแท็บ (\t, คือการเคาะเว้นย่อหน้า) รวมถึงการขึ้นบรรทัดใหม่ (\n)
ตัวอย่าง เช่น
หาส่วนประกอบที่เป็นตัวหนังสือที่ไม่ใช่ตัวเลขสองตัวซึ่งคั่นด้วยช่องว่าง
คำค้น |
ข้อความ | ผลการค้น In ciascuna epoca, i|l pastore compare per sconfiggere l|e tenebre |
กลุ่มคำที่เข้าข่าย n ca e, il pe ce pr se le t |
ที่จริงตัวอย่างนี้จะใช้ช่องว่าง " " แทน \s นั่นคือ '\D \D'
ก็ได้ผลเช่นเดียวกัน (ช่องว่างก็นับเป็นอักษรตัวหนึ่ง)
แต่ \s นั้นจะรวมแท็บและการขึ้นบรรทัดใหม่ (\n) ด้วย ตัวอย่างเช่น
คำค้น |
ข้อความ | ผลการค้น Tuttavia quando l|a pace viene risbalita, scompare |
กลุ่มคำที่เข้าข่าย a qo la pe ve r, s |
และหากต้องการให้อักษรตัวหนึ่งแทนอะไรก็ได้ ก็ให้ใช้ . (จุด) เช่น
คำค้น |
ข้อความ | ผลการค้น del dal della dalla dei dai degli dagli delle dalle dello dallo |
กลุ่มคำที่เข้าข่าย del ddelladei ddeglidelledello |
เพียงแต่ว่ากรณีที่ต้องการจะค้นหาอักษรจุดจริงๆจะต้องใช้ \ นำหน้ากลายเป็น \.
แบบนี้ ไม่เช่นนั้นจะกลายเป็นการหาตัวอะไรก็ได้ไป เช่น
คำค้น |
ข้อความ | ผลการค้น a. a, a; a: |
กลุ่มคำที่เข้าข่าย a.a,a;a: |
แต่พอลองใส่ \ นำหน้าจึงจะกลายเป็นการหาแค่ a.
คำค้น |
ข้อความ | ผลการค้น a. a, a; a: |
กลุ่มคำที่เข้าข่าย a. |
ไม่ใช่แแค่จุดเท่านั้น มีเครื่องหมายอีกหลายตัวที่ทำหน้าที่พิเศษ เช่น
()[]{}|+*?\^$ ซึ่งจะกล่าวถึงต่อไป หากต้องการค้นอักษรพวกนี้จริงๆจำเป็นต้องใส่ \
นำหน้า แม้แต่ตัว \ เองก็ด้วย
หากใส่ \\ จะหมายถึงการหาตัว \ ตัวเดียว เช่นถ้าหากใส่ \\. แบบนี้จะหมายถึงค้นหา
\ แต่จุดที่อยู่หลัง . จะหมายถึงการหาตัวอักษรใดๆ ตามความสามารถเดิมของมัน
คำค้น |
ข้อความ | ผลการค้น \ก/ \ふ/ \\./ \\으// |
กลุ่มคำที่เข้าข่าย \ก/\ふ/\./\으/ |
การกำหนดชุดตัวอักษรที่เข้าข่ายตามที่ต้องการ (ใช้วงเล็บเหลี่ยม [ ])
กลุ่มตัวอักษรชนิดที่กำหนดด้วยแบ็กสแลชนั้นแค่เป็นการแบ่งกลุ่มแบบคร่าวๆ
แต่ก็อาจมีบ่อยครั้งที่เราต้องการเจาะจงอักษรบางกลุ่มที่กำหนดขึ้นเอง
กรณีแบบนี้สามารถกำหนดกลุ่มตัวอักษรตามที่ต้องการเอาเองได้โดยใช้วงเล็บเหลี่ยมล้อม
[ ] แล้วใส่อักษรที่ต้องการทั้งหมดในนั้น
เช่น ลองหาคำที่เป็นอักษรกลางตามด้วยอะไรก็ได้อีกตัวนึง ก็เอา [ ]
คร่อมอักษรที่ต้องการทั้งหมดไว้
คำค้น |
ข้อความ | ผลการค้น ไก่|จิ|กเ|ด็|กตายบน|ปา|กโ|อ่งใบหนึ่งที่วางอยู่หน้าบ้าน |
กลุ่มคำที่เข้าข่าย ก่จิกเด็กตบนปากโอ่บหอยบ้ |
หากมีอักษรหลายตัวที่ต้องการให้เข้าข่ายก็จะต้องเขียนไล่ไปทั้งหมด เช่นต้องการ a
ถึง m ก็ต้องพิมพ์ [abcdefghijklm] แบบนี้ดูแล้วค่อนข้างยาว
แต่หากอักษรที่ต้องการนั้นเป็นตัวที่ลำดับติดกันแบบนี้
มีวิธีการเขียนที่ง่ายขึ้นเพื่อความสะดวก นั่นคือใช้เครื่องหมาย -
เพื่อแสดงช่วง
เช่น ถ้าใส่ [a-y] หมายถึงอักษรตั้งแต่ a ถึง y [ก-ช] หมายถึงอักษรตั้งแต่ ก ถึง
ช เป็นต้น
ลำดับอักษรในที่นี้เป็นลำดับที่เรียงตามเลขในยูนิโค้ด
สำหรับภาษาไทยแล้วอักษรตัวแรกสุดคือ "ก" และตัวสุดท้ายคือเลข "๙"
ดังนั้นหากต้องการแสดงถึงอักษรไทยทั้งหมดก็เขียนเป็น [ก-๙]
หากเขียน [ก-ฮ] จะเท่ากับ [กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮ]
นั่นคือพยัญชนะทั้ง ๔๔ ตัว รวม "ฤ" กับ "ฦ" ด้วย
เพราะตามหลักเวลาเปิดพจนานุกรม "ฤ" กับ "ฦ" จะแทรกอยู่ลำดับถัดจาก "ร" และ "ล"
ดังนั้นในยูนิโค้ดก็เรียงโดยยึดตามนี้ด้วย
สำหรับอักษรจีนจะใช้ [一-龥] เพื่อครอบคลุมทุกตัวอักษร
ส่วนอักษรญี่ปุ่นฮิรางานะใช้ [ぁ-ゞ] และคาตาคานะใช้ [ァ-ヶ]
ตัวอย่างเช่น
คำค้น |
ข้อความ | ผลการค้น ฉันเป็นใค|ร มาจากไห|น จะไปไห|น |
กลุ่มคำที่เข้าข่าย ฉนปนครมจกหนจปหน |
ในทางตรงข้าม ถ้าต้องการเอาอักษรทุกตัวยกเว้นบางตัวก็จะใช้ ^
มาใส่เป็นตัวขึ้นต้นในวงเล็บเหลี่ยม เช่น
คำค้น |
ข้อความ | ผลการค้น ฉันเป็นใคร มาจากไหน จะ|ไปไหน |
กลุ่มคำที่เข้าข่าย ัเ็ใ าาไ ะไไ |
ผลที่ได้ตรงข้ามกับตัวอย่างที่แล้ว
อักษร - ที่ใช้คั่นระหว่าง ๒ อักษรที่ต้องการนี้ถือเป็นอักษรพิเศษในกรณีนี้
ไม่ได้ถูกตีความเปํนอักษรตัวหนึ่ง เช่น [ค-ญ] ไม่ได้หมายถึงอักษร ค หรือ - หรือ ญ
แต่หมายถึงอักษรตั้งแต่ ค ถึง ญ
แต่ว่าหากต้องการให้ - รวมอยู่ในกลุ่มที่เข้าข่ายด้วยก็ให้วางไว้เป็นตัวแรก
เพราะหากวางไว้ต่อจากตัวอักษรอื่นจะกลายเป็นการกำหนดช่วงตั้งแต่อักษรตัวนั้นไปจนถึงอักษรที่อยู่ทางขวา
เช่นตัวอย่างนี้หมายถึงค้นตัวที่อยู่ระหว่าง + ถึง ÷
คำค้น |
ข้อความ | ผลการค้น 1+2 3-4 5×6 7÷8 ~~~** |
กลุ่มคำที่เข้าข่าย 1+23-45×67÷8 |
จะเห็นว่าที × ด้วย ทั้งๆที่ไม่ได้ใส่ × มาด้วย
ส่วนถ้าเขียน -+÷ แบบนี้จะกลายเป็นการค้นแค่ -+÷ ๓ ตัวนี้
คำค้น |
ข้อความ | ผลการค้น 1+2 3-4 5×6 7÷8 ~~~** |
กลุ่มคำที่เข้าข่าย 1+23-47÷8 |
ถ้าหากอักษรที่ใส่ไปตัวหน้า - อยู่ในลำดับยูนิโค้ดหลัง -
ก็จะเกิดข้อผิดพลาดขึ้น เช่น
คำค้น |
ข้อความ | ผลการค้น ※ มีบางอย่างผิดพลาด ※ |
กลุ่มคำที่เข้าข่าย ※ มีบางอย่างผิดพลาด ※ |
ตัวอย่างนี้ผิดพลาดเพราะ + มาทีหลัง * ตามลำดับยูนิโค้ด
ทั้งอักษร + และ * นี้ที่จริงก็เป็นอักษรที่มีความหมายพิเศษเช่นกัน
(ซึ่งจะกล่าวถึงในหัวข้อถัดไป) เพียงแต่หากอยู่ภายในวงเล็บเหลี่ยม [ ]
แล้วความหมายของอักษรบางตัวจะเปลี่ยนไป
อักษรบางตัวที่เดิมทีมีความหมายพิเศษก็จะไม่มีความหมายพิเศษอะไรเมื่ออยู่ใน [
]
การกำหนดให้อักษรมีกี่ตัวก็ได้ (ใช้ +)
หากมีอักษรที่ต้องการให้มีแต่ไม่ได้เจาะจงว่าจะต้องมีกี่ตัว
จะมีหนึ่งตัวหรือกี่ตัวก็ได้ กรณีแบบนี้ให้เติม + ตามหลังตัวอักษรที่ต้องการ
เช่น ต้องการตัวที่ "ก" ตามหลังตัวเลขอะไรก็ได้กี่ตัวก็ได้
คำค้น |
ข้อความ | ผลการค้น ก12a กฮ21 pก324 บวก7777 31ก |
กลุ่มคำที่เข้าข่าย ก12ก324ก7777 |
กรณีที่เป็นชุดอักษรที่กำหนดด้วยกรอบ [] ก็ใส่ + ได้เช่นกัน เช่น
ลองหาอักษรที่เป็นพยัญชนะ (ก-ฮ) ที่อยู่ติดกัน
คำค้น |
ข้อความ | ผลการค้น กากมากย่อยยากนะ |
กลุ่มคำที่เข้าข่าย กกมกยอยยกน |
แบบนี้จะเห็นว่าพยัญชนะอะไรก็ได้ที่อยู่ติดกันก็จะรวมอยู่ในกลุ่มเดียวกัน
การกำหนดให้อักษรมีหรือไม่มีก็ได้ (ใช้ ? และ *)
หากเติมเครื่องหมายคำถาม ?
ลงข้างหลังตัวอักษรจะหมายความว่าอักษรตัวนั้นจะมีหรือไม่มีอยู่ก็ได้
ตัวอย่างเช่น
คำค้น |
ข้อความ | ผลการค้น h1 h h36 h|h |
กลุ่มคำที่เข้าข่าย h1hh3hh |
และถ้าใช้ดอกจัน * จะหมายถึงว่าจะมีหรือไม่มีก็ได้และถ้ามีจะมีกี่ตัวก็ได้
คำค้น |
ข้อความ | ผลการค้น ส ส39 ส1 ส4567 สศ9 ชส0 |
กลุ่มคำที่เข้าข่าย สส39ส1ส4567สส0 |
ข้อแตกต่างระหว่าง * กับ + ก็คือ + จะต้องมีอย่างน้อย ๑ ตัว แต่ *
จะไม่มีเลยก็ได้
การกำหนดให้อักษรมีจำนวนตามที่กำหนด (ใช้วงเล็บปีกกา { })
ปกติแล้วต้องการให้มีอักษรกี่ตัวก็ต้องเขียนอักษรไปเป็นจำนวนเท่านั้น เช่นตัวเลข
๔ ตัวก็เขียน \d\d\d\d แต่ว่าหากมีจำนวนมากการเขียนแบบนี้จะยาว
การใช้วงเล็บปีกกาจะช่วยให้การเขียนสั้นลงได้
โดยเขียนตัวที่ต้องการซ้ำแล้วตามด้วยวงเล็บปีกกาที่คร่อมด้วยจำนวนที่ต้องการ
ตัวอย่างเช่น ต้องการตัวเลขยาวต่อกัน ๓ ตัว อาจเขียนว่า \d{3} แทนที่จะเขียนเป็น
\d\d\d
คำค้น |
ข้อความ | ผลการค้น 123x456x789x00 |
กลุ่มคำที่เข้าข่าย 123456789 |
แต่บางครั้งจำนวนก็อาจไม่ได้รู้แน่ชัดแต่มีขอบเขตที่แน่นอนอยู่ค่าหนึ่ง
แบบนั้นก็สามารถใส่จุลภาค , ไว้ใน {} โดยจำนวนที่อยู่ทางซ้าย , คือขอบเขตล่าง
ถ้าไม่ใส่คือ 0 ทางขวา , คือขอบเขตบน ถ้าไม่ใส่คือไม่จำกัดขอบเขต
\d{2,3} เท่ากับ \d\d\d? คือตัวเลข ๒ ถึง ๓ ตัว
\d{,3} เท่ากับ \d{0,3} หรือ \d?\d?\d? คือตัวเลขไม่เกิน ๓ ตัว
\d{2,} เท่ากับ \d\d+ หรือ \d\d\d* คือตัวเลข ๒ ตัวขึ้นไป
ตัวอย่าง หาเลขโทรศัพท์ ซึ่งควรจะขึ้นต้นด้วย 0 แล้วมีความยาว ๙ ถึง ๑๐ ตัว
คำค้น |
ข้อความ | ผลการค้น 023456789 0897654321 01234567 123456789 |
กลุ่มคำที่เข้าข่าย 0234567890897654321 |
โลภมากหรือไม่โลภมาก (ใช้ ?)
ข้อควรระวังที่สำคัญอย่างหนึ่งในการใช้ + หรือ * ก็คือ ปกติแล้วเวลาที่ใช้ + หรือ
* นั้นจะมีอักษรถูกรวมอยู่ในกลุ่มกี่ตัวก็เป็นไปได้
ซึ่งในบางครั้งก็ทำให้เกิดความคลุมเครือว่าต้องการกี่ตัวกันแน่
และทำให้เกิดผลที่ไม่ได้คาดหวังขึ้นมาได้
ยกตัวอย่างเช่นถ้าเราต้องการค้นหาคำอะไรก็ได้ยาวแค่ไหนก็ได้ที่ลงท้ายด้วยสระ "า"
ก็อาจเขียนเป็น '\S+า' เช่น
คำค้น |
ข้อความ | ผลการค้น พลังคลื่นเต่าสะท้านฟ้า! |
กลุ่มคำที่เข้าข่าย พลังคลื่นเต่าสะท้านฟ้า |
จะเห็นว่าพอเขียนแบบนี้แล้ว \S+ จะแทนตัวอักษรตั้งแต่ตัวแรกจนถึงก่อน "า"
ตัวสุดท้าย
แต่ในความเป็นจริงก็มี "า" นำหน้าอยู่ก่อนตั้ง ๒ ตัวซึ่งถ้าจะนับรวมถึงแค่ "า"
ตัวแรกก็ยังถือว่าเข้าข่ายรูปแบบที่ต้องการอยู่ดี
แต่ว่าโดยทั่วไปแล้วโปรแกรมจะพยายามหากลุ่มอักษรที่เข้าข่ายให้ยาวที่สุดดังนั้นต่อให้เจออักษรที่เข้าข่าวตามที่ต้องการแล้วหากไล่ตัวต่อไปดูแล้วยังเข้าข่ายอยู่มันก็จะนับต่อไปจนสุด
ลักษณะแบบนี้เรียกว่าเป็นการจับกลุ่มแบบ "โลภมาก"
แต่เราสามารถทำให้โปรแกรมหยุดหาต่อทันทีที่เจอกลุ่มตัวอักษรที่เข้าข่ายครบในขั้นต่ำ
ซึ่งทำได้โดยการเติม ? ลงไปต่อท้าย + หรือ * เช่น
คำค้น |
ข้อความ | ผลการค้น พลังคลื่นเต่า|สะท้า|นฟ้า! |
กลุ่มคำที่เข้าข่าย พลังคลื่นเต่าสะท้านฟ้า |
พอทำแบบนี้แล้วเมื่อเจอ "า" ก็จะแยกเป็นก้อนหนึ่งทันที
ลักษณะแบบนี้เรียกว่าเป็นการจับกลุ่มแบบ "ไม่โลภมาก"
คือพอได้ตามเงื่อนไขแล้วก็พอเลย ไม่เอาต่อแล้ว
จะเป็นแบบโลภมากหรือไม่นั้นต่างกันแค่เติม ? ต่อท้ายหรือไม่เท่านั้น
? ในที่นี้มีความหมายต่างจาก ?
ที่ตามหลังตัวอักษรทั่วไปเพื่อแทนการมีหรือไม่มีก็ได้ของตัวนั้น
และมันสามารถตามหลัง + หรือตามหลัง * หรือ {} หรือแม้แต่ ? เองก็ได้
ตัวอย่างอื่นๆ เช่น
คำค้น |
ข้อความ | ผลการค้น กกกกก|กกกก |
กลุ่มคำที่เข้าข่าย กกกกกกกกก |
แบบนี้คือโลภมาก ถ้าเอา ๕ อันได้ก็เอา ถ้ามีไม่ครบ ๕
ก็ค่อยพอใจอยู่แค่นั้น
ส่วนแบบนี้คือไม่โลภมาก เจอแค่ ๒
ซึ่งเป็นขั้นต่ำก็หยุดแล้ว
คำค้น |
ข้อความ | ผลการค้น กก|กก|กก|กกก |
กลุ่มคำที่เข้าข่าย กกกกกกกก |
อีกตัวอย่าง คราวนี้ใช้กับ *
โลภมาก
คำค้น |
ข้อความ | ผลการค้น ปลาทู-ปลาเก๋า-ปลากระพง-ปราจีนบุรี |
กลุ่มคำที่เข้าข่าย ปลาทูปลาเก๋าปลากระพง |
ไม่โลภมาก
คำค้น |
ข้อความ | ผลการค้น ปลาทู-ปลาเก๋า-ปลากระพง-ปราจีนบุรี |
กลุ่มคำที่เข้าข่าย ปลาปลาปลา |
กรณีที่ regex ทั้งหมดมีแต่ส่วนที่ใช้ * หรือ ? นั้นจำนวนอักษรขั้นต่ำคือ 0
หมายความว่าถึงไม่มีเลยก็นับ ซึ่งอาจชวนให้เป็นห่วงว่าเวลาค้นแบบไม่โลภมาก (เติม
?) จะได้สายอักขระว่าง "" เป็นจำนวนไม่สิ้นสุด
แต่ในความเป็นจริงแม้จะไม่นับเลยก็ยังไล่ไปยังอักษรตัวถัดไป ดังนั้นจึงไม่มีปัญหา
โลภมาก
คำค้น |
ข้อความ | ผลการค้น 5555| |
กลุ่มคำที่เข้าข่าย 5555 |
ไม่โลภมาก
คำค้น |
ข้อความ | ผลการค้น 5555 |
กลุ่มคำที่เข้าข่าย |
โลภมาก
คำค้น |
ข้อความ | ผลการค้น la|hl|la|la| |
กลุ่มคำที่เข้าข่าย lallala |
ไม่โลภมาก
คำค้น |
ข้อความ | ผลการค้น lahllala |
กลุ่มคำที่เข้าข่าย |
การคัดกรองให้เข้าข่ายเฉพาะเริ่มต้นและปิดท้ายสายอักขระ (ใช้ ^ หรือ $)
หากต้องการให้เข้าข่ายแค่เฉพาะเมื่อคำนั้นอยู่ที่ตำแหน่งแรกของสายอักขระเท่านั้นให้ใส่
^ นำหน้า
และหากต้องการให้เข้าข่ายแค่เฉพาะเมื่อคำนั้นอยู่ที่ตำแหน่งท้ายสุดก็ใส่ $
ต่อท้าย
ตัวอย่างเช่น กรณีเอาเฉพาะเมื่อขึ้นต้นคำ
คำค้น |
ข้อความ | ผลการค้น saa shhh |
กลุ่มคำที่เข้าข่าย saa |
กรณีเอาเฉพาะเมื่อลงท้ายคำ
คำค้น |
ข้อความ | ผลการค้น saa shhh |
กลุ่มคำที่เข้าข่าย shhh |
ตัวเลือกเสริมให้การเริ่มบรรทัดใหม่ถือเป็นจุดตั้งต้นคำเมื่อใช้ ^ ปกติแล้วผลที่ได้จะออกมาแค่คำเดียวเท่านั้น
คือดูแค่คำที่อยู่ต้น เพราะคำอื่นนอกจากที่อยู่อักษรตัวแรกไม่มีทางเข้าข่าย
$ ก็เช่นเดียวกัน คำที่เข้าข่ายจะต้องอยู่ตรงท้ายสุดเท่านั้น
อย่างไรก็ตาม ปกติเวลาใช้ regex มักจะมีตัวเลือกเสริม หรือที่เรียกว่าแฟล็ก
(flag) ให้เลือก
โดยมีตัวเลือกหนึ่งคือ m หรือชื่อเต็มคือ MULTILINE
ตัวเลือกนี้ถ้าหากเลือกแล้วจะทำแต่ละบรรทัดคิดแยกกัน
ต้นบรรทัดก็ถือเป็นจุดเริ่มต้นคำ จึงเข้าข่ายเมื่อใช้ ^
และท้ายบรรทัดก็ถือเป็นท้ายคำ จึงเข้าข่ายเมื่อใช้ $
ลองใส่ตัวเลือกนี้แล้วค้นด้วย $ ดู
จะพบว่าขอแค่อยู่ท้ายบรรทัดแล้วตรงตามเงื่อนไขก็จะเข้าข่าย
แต่ถ้าลองไม่ใส่ตัวเลือกนี้
จะมีเฉพาะตัวสุดท้ายของบรรทัดสุดท้ายเท่านั้นที่เข้าข่าย
คำค้น |
ข้อความ | ผลการค้น ร้างรา โรยรา เลิกร้าง ล้มล้าง เลิกรา ร่ำลา |
กลุ่มคำที่เข้าข่าย ร่ำลา |
ถ้าเขียนโปรแกรม ในแต่ละภาษาก็มีวิธีการใส่ตัวเลือกเสริมแบบนี้ต่างกันออกไป
จาวาสคริปต์หรือรูบีก็แค่เติม m ต่อท้าย เช่น /\s+า$/m ส่วนในไพธอนต้องเติม re.M
หรือ re.MULTILINE
ตัวเลือกเสริมให้ไม่แยกแยะตัวพิมพ์เล็กพิมพ์ใหญ่ ตัวเลือกเสริมอีกอย่างที่สำคัญก็คือ
การพิจารณาว่าจะแยกแยะตัวพิมพ์ใหญ่พิมพ์เล็กหรือเปล่า
ปกติแล้วเวลาใช้ regex ตัวอักษรโรมันเช่นภาษาอังกฤษนั้น
พิมพ์เล็กกับพิมพ์ใหญ่จะถือเป็นคนละตัวกัน
ดังนั้นถ้าค้นแค่ตัวพิมพ์เล็กในการค้นหา ตัวพิมพ์ใหญ่จะไม่ได้ถูกค้นเจอด้วย
คำค้น |
ข้อความ | ผลการค้น Æ æ B b Ç ç D d É é F f Δ δ あ ぁ ア |
กลุ่มคำที่เข้าข่าย æbçéΔあ |
แต่ก็สามารถใส่ตัวเลือกเสริมให้ไม่มีการแยกแยะตัวพิมพ์เล็กพิมพ์ใหญ่ได้
ซึ่งมีผลทั้งอักษรโรมันปกติ และอักษรพิเศษอย่าง æ ç é รวมถึงอักษรกรีกอย่าง δ/Δ
(เดลตา) ด้วย แต่ไม่มีผลใดๆกับอักษรญี่ปุ่น
เพียงแต่ว่าใน php จะมีผลเฉพาะตัวอักษร a-z ธรรมดาเท่านั้น พวก æ ç é
หรืออักษรกรีก จะยังคงแยกพิมพ์เล็กพิมพ์ใหญ่
เวลาเขียนโปรแกรม ในจาวาสคริปต์หรือรูบีให้เติม i ต่อท้าย เช่น /[æçéΔあ]/i
ส่วนในไพธอนต้องเติม re.I หรือ re.IGNORECASE
การคัดกรองให้เข้าข่ายเฉพาะเมื่ออยู่ต้นหรือท้ายคำ (ใช้ \b)
^ กับ $
นั้นจะใช้กรณีที่คัดคำที่อยู่ต้นหรือท้ายของทั้งบรรทัดหรือทั้งสายอักขระเท่านั้น
(แล้วแต่ตัวเลือกเสริม)
กรณีที่ต้องการคัดเอาเฉพาะคำที่แค่อยู่ต้นหรือท้ายคำแต่ไม่ใช่ต้นหรือท้ายของทั้งสายอักขระ
แบบนี้จะใช้ \b
ความหมายของต้นคำและท้ายคำนี้ขึ้นอยู่กับความหมาย \w และ \W กล่าวคือ \b
จะเข้าข่ายเมื่อเจอตัวที่เข้าข่าย \w แล้วต่อด้วยตัวที่เป็น \W (คือไม่ใช่ \w)
หรือเจอ \w ที่นำหน้าด้วย \W
ดังนั้นความหมายของ \b นี้จะต่างกันไปขึ้นอยู่กับความหมายของ \w ด้วย ในไพธอน \w
จะมีความหมายรวมถึงอักษรสำหรับสร้างคำในแต่ละภาษา
ดังนั้นตัวที่ถือเป็นตัวกั้นคำก็คือพวกสัญลักษณ์ต่างๆ เช่น
,./?!\<>[]{}()*&^%$#@~ ยกเว้นแค่ _ เท่านั้น
แต่ในจาวาสคริปต์, รูบี และ php นั้น \w
จะรวมแค่อักษรภาษาอังกฤษและตัวเลขเท่านั้น
ทำให้อักษรภาษาอื่นก็กลายเป็นตัวกั้นไปด้วย
ตัวอย่าง
คำค้น |
ข้อความ | ผลการค้น (ใน javascript, ruby, php) หsศ rกd สจl*plส wuไ iล+รgห |
กลุ่มคำที่เข้าข่าย rกd*plล+ร |
จะเห็นว่าคำที่เข้าข่ายนั้นคือพวกที่ขึ้นต้นและลงท้ายด้วยตัวอักษรภาษาอังกฤษ
นอกจากนี้ *pl ก็เข้าข่ายมาด้วยแบบน่าประหลาด ที่เป็นแบบนี้ก็เพราะว่า *
อยู่ในกลุ่ม \W แต่ทางซ้ายของ * เป็น l ซึ่งอยู่ในกลุ่ม \w แต่ทางขวาลงท้ายด้วย l
ซึ่งอยู่ในกลุ่ม \w แต่ตัวถัดมาเป็น ส ซึ่งอยู่ในกลุ่ม \W
แต่ในไพธอน การตีความ \w จะต่างไป ผลจะเป็นดังนี้
คำค้น |
ข้อความ | ผลการค้น (ใน python) หsศ rกd สจl*plส wuไ iล+|รgห |
กลุ่มคำที่เข้าข่าย หsศrกdสจlplสwuไiล+รgห |
ส่วน \B จะตรงกันข้ามกับ \b คือจะทำให้เข้าข่ายในกรณีที่ไม่อยู่ริม
คำค้น |
ข้อความ | ผลการค้น a la ah lah aa |
กลุ่มคำที่เข้าข่าย aaa |
คำค้น |
ข้อความ | ผลการค้น a la ah lah aa |
กลุ่มคำที่เข้าข่าย aaa |
การกำหนดกลุ่มคำที่ตามด้วยคำที่ต้องการ (ใช้ (?= ) และ (?! ))
บางครั้งเราอาจต้องการหากลุ่มอักษรที่เข้าข่ายที่ต้องการกลุ่มหนึ่ง
แต่ไม่ได้ต้องการจะเอามันมาใช้ทั้งหมด เช่นว่า
"อยากได้อักษรนี้แค่เฉพาะเมื่ออยู่หน้าอักษรนี้" เป็นต้น ในกรณีแบบนี้สามารถใช้
?=
เช่น ถ้าต้องการตัวอักษรอะไรก็ได้ที่นำหน้า a แต่ไม่เอา a ด้วย ให้เขียนแบบนี้
คำค้น |
ข้อความ | ผลการค้น bakadana omae |
กลุ่มคำที่เข้าข่าย bkdnm |
เพราะถ้าเราตัด (?= ) ออกไป เหลือแค่ \Sa เฉยๆ จะหมายความว่าเราเอา a ด้วย
คำค้น |
ข้อความ | ผลการค้น ba|ka|da|na omae |
กลุ่มคำที่เข้าข่าย bakadanama |
ดังนั้นการที่ใส่ (?= ) จึงเป็นการตัด a ออกจากกลุ่มที่จะเอา เอาแค่ตัวข้างหน้า
ในทางตรงกันข้าม เราอาจจะ "อยากได้ตัวนี้เฉพาะเมื่อไม่นำหน้าตัวนี้"
กรณีแบบนี้ให้ใช้ ?!
เช่นต้องการหาพยัญชนะสักตัวที่ไม่ตามด้วย a
คำค้น |
ข้อความ | ผลการค้น gekikarai kamaboko |
กลุ่มคำที่เข้าข่าย gkbk |
การกำหนดกลุ่มคำที่มาหลังคำที่ต้องการ (ใช้ (?<= ) และ (?<! ))
ในทำนองเดียวกันกับข้อที่แล้ว บางครั้งเราอาจจะมีเงื่อนไขว่า
"อยากได้อักษรนี้แค่เฉพาะเมื่ออยู่หลังอักษรนี้" กรณีแบบนี้อาจใช้ (?<= )
เพียงแต่ว่ารูปแบบการเขียนนี้
ไม่สามารถใช้ในจาวาสคริปต์ได้
ต้องใช้ในไพธอนหรือรูบีเท่านั้น ถ้าใช้ในจาวาสคริปต์ก็จะเกิดข้อผิดพลาดขึ้น
ดังนั้นตัวอย่างต่อไปนี้ต้องทดลองในไพธอน, รูบี หรือ php เอา
ถ้าหากลองในโปรแกรมที่เตรียมไว้ซึ่งเขียนด้วยจาวาสคริปต์ดูจะเกิดข้อผิดพลาดขึ้น
ตัวอย่างเช่น หาอักษรที่ตามด้วย "เ" แต่ไม่เอา "เ" ด้วย
คำค้น |
ข้อความ | ผลการค้น (ใน python, ruby, php) เวเนซูเอลา |
กลุ่มคำที่เข้าข่าย วนอ |
และในทางตรงกันข้าม ถ้า "อยากได้อักษรนี้แค่เฉพาะเมื่อไม่อยู่หลังอักษรนี้" ก็ใช้
(?<! ) อันนี้ก็ใช้ในจาวาสคริปต์ไม่ได้เช่นเดียวกัน
การเลือกเอาแค่บางส่วน (ใช้วงเล็บโค้ง ( ))
การใช้ (?= ) หรือ (?<= ) ดังตัวอย่างที่ผ่านมานั้นอาจเข้าใจยาก
อีกทั้งยังใช้ในจาวาสคริปต์ไม่ได้ด้วย แต่ก็มีวิธีที่สามารถใช้แทนได้อยู่
นั่นคืออาจใช้วงเล็บโค้งล้อมรอบเฉพาะส่วนที่ต้องการ
ตัวอย่างเช่น ต้องการเอาพยัญชนะที่อยู่หลัง "เ" แต่ไม่เอา "เ" ด้วย
ก็ให้วงเล็บที่อักษรหลัง "เ" ไว้ ทำแบบนี้จะได้ผลลัพธ์ออกมา ๒ ส่วน
โดยกลุ่มคำทั้งหมดจะเรียกว่า \0 ส่วนเฉพาะที่อยู่ในวงเล็บจะเรียกว่า \1
เราสามารถเลือกหยิบมาเฉพาะส่วน \1 ได้
คำค้น |
ข้อความ | ผลการค้น เว|เนซูเอลา |
กลุ่มคำที่เข้าข่าย วนอ |
แบบนี้ก็จะได้ผลเหมือนตัวอย่างที่แล้ว
ตัวอย่างเช่น เอาพยัญชนะที่อยู่หน้า "า" แต่ไม่เอา "า" ด้วย
ก็ให้วงเล็บที่อักษรหน้า "า" ไว้ ทำแบบเดียวกัน
คำค้น |
ข้อความ | ผลการค้น อา|ตา|กา|มา |
กลุ่มคำที่เข้าข่าย อตกม |
ถ้าใส่วงเล็บหลายตัว ก็จะได้กลุ่มเพิ่มมา กลุ่มที่ ๒ เรียกว่า \2 ส่วนกลุ่มที่ ๓
นั้นจะเรียกว่า \3 ตามลำดับ
คำค้น |
ข้อความ | ผลการค้น มานะ|ราคะ|ซาบะ |
กลุ่มคำที่เข้าข่าย นคบ |
พอจัดกลุ่มก้อนใส่หมายเลขแบบนี้แล้วสามารถเลือกว่าจะหยิบส่วนไหนมาทำอะไรได้
ซึ่งจะกล่าวถึงในหัวข้อต่อๆไป
การนำกลุ่มก้อนมาอ้างอิงเพื่อหาส่วนที่ปรากฏซ้ำ (ใช้ \หมายเลข) กลุ่มก้อนข้อความที่ล้อมด้วยวงเล็บสามารถนำมาใช้อ้างอิงซ้ำได้
โดยเขียนแทนด้วย \1 และ \2 ลงใน regex ไปเลย
เช่น ต้องการอักษรที่ขนาบกันคั่นด้วยอักษรตัวนึง
เราก็สามารถใช้วงเล็บล้อมที่อักษรตัวแรก แล้วใช้ \1 เพื่อแทนตัวขวา
คำค้น |
ข้อความ | ผลการค้น 909 191 775 343 ฯลฯ |
กลุ่มคำที่เข้าข่าย 909191343ฯลฯ |
หรือทำอะไรที่ซับซ้อนขึ้นแบบนี้ก็ได้
คำค้น |
ข้อความ | ผลการค้น 19091 6558556 12912 77557 33433 ฯลฯ |
กลุ่มคำที่เข้าข่าย 19091655855633433ฯลฯ |
การใช้ regex เพื่อแทนที่
ที่ผ่านมาเราแค่ใช้ regex เพื่อตามหาคำที่ต้องการเท่านั้น
แต่ว่าในการใช้งานจริงบ่อยครั้งที่เราตามหาเพื่อจะแทนที่ด้วยค่าที่ต้องการ
กรณีนี้นอกจากจะเลือกค้นหาธรรมดาเราสามารถปรับโหมดเป็นแทนที่ได้
การแทนที่ข้อความนั้นถ้าเป็นในจาวาสคริปต์ใช้ชื่อเมธอดว่า replace
ในไพธอนจะใช้ชื่อว่า sub ส่วนในรูบีจะใช่ชื่อว่า gsub ใน php จะเป็น
preg_replace
เช่น ถ้าต้องการหาสระ "ะ" หรือ "า" แล้วแทนด้วย a
คำค้น |
ข้อความ | ผลการค้น ทaกaมaงaฮaรa |
กลุ่มคำที่เข้าข่าย าาะะาะ |
แต่บางครั้งเราอาจต้องการแทนที่โดยใช้กลุ่มที่เราค้นเจอเป็นตัวอ้างอิงอีกที
แบบนี้ก็ให้แทนด้วย \0 หรือ \1
เช่นแทนที่ไม้ยมก "ๆ" ด้วยคำที่นำหน้ามัน
คำค้น |
ข้อความ | ผลการค้น มากมาก หลายหลาย ยุ่งยุ่ง |
กลุ่มคำที่เข้าข่าย มาก ๆหลายๆยุ่ง ๆ |
นอกจากนี้เมธอดที่ใช้ในการแทนที่อักษรนั้นมักจะมีความสามารถในการกำหนดฟังก์ชันในการแทน
ทำให้สามารถกำหนดรูปแบบการแทนได้อย่างอิสระ
อันนี้จะค่อนข้างซับซ้อนและต่างกันไปตามภาษาต่างๆ ดังนั้นจึงไม่ขอลงรายละเอียด
การใช้ regex เพื่อแยกส่วนคำ อีกงานที่ regex มักถูกใช้คือเวลาที่ต้องการแยกคำออกเป็นส่วนๆ
โดยใช้ค้นหาอักษรที่จะใช้เป็นตัวแยก
เมธอดสำหรับแยกในภาษาต่างๆเช่นจาวาสคริปต์, ไพธอน, รูบี จะชื่อว่า split แต่ใน
php จะใช้ชื่อว่า preg_split
ตัวอย่าง
คำค้น |
ข้อความ | ผลการค้น อาริฮาระ ชิโนโนเมะ-โนซากิ คาวากิตะ, อุกิตะ นากาโนะ ผลการตัด: |
1.
| อาริฮาระ |
2.
| ชิโนโนเมะ |
3.
| โนซากิ |
4.
| คาวากิตะ |
5.
| อุกิตะ |
6.
| นากาโนะ |
|
กลุ่มคำที่เข้าข่าย - , |
การจับกลุ่มก้อนเฉยๆ (ใช้ (?: ))
บางครั้งเราอาจเพียงต้องการใส่วงเล็บเพื่อต้องการจะใช้ให้พิจารณารวมเป็นกลุ่มก้อนเท่านั้น
ไม่ได้ต้องการที่จะเน้นหรือว่าให้หมายเลขกับก้อนนั้นเพื่อจะเอามาทำอะไร
กรณีแบบนี้ให้เติม ?: ลงไปขึ้นต้นในวงเล็บ
ปกติถ้าใส่วงเล็บไปแบบธรรมดาจะกลายเป็นกลุ่มที่มีหมายเลขกำกับแบบนี้
คำค้น |
ข้อความ | ผลการค้น skskskan lllag sprspram |
กลุ่มคำที่เข้าข่าย anagam |
แต่ถ้าวงเล็บไหนเติม ?: เข้าไปจะไม่นับเป็นกลุ่มที่ติดหมายเลข
คำค้น |
ข้อความ | ผลการค้น skskskan lllag sprspram |
กลุ่มคำที่เข้าข่าย anagam |
การตั้งให้รูปแบบเปลี่ยนไปตามเงื่อนไข (ใช้ (?( ) | ) )
หากมีกลุ่มก้อนอักษรที่ใช้ ? หรือ * อยู่
อักษรกลุ่มนั้นอาจมีตัวตนอยู่หรือไม่ก็ได้
และในบางครั้งเราอาจต้องการให้รูปแบบที่จะตามมานั้นเปลี่ยนไปโดยขึ้นกับว่า
กลุ่มนี้มีอยู่หรือเปล่า
สามารถทำได้โดยใส่ส่วนที่ต้องการให้เปลี่ยนตามเงื่อนไขในรูป
(?(เลขกลุ่ม)รูปแบบเมื่อมี|รูปแบบเมื่อไม่มี)
ที่อยู่ในวงเล็บด้านในก็คือตัวเลขที่แทนกลุ่มที่ต้องการให้เป็นตัวกำหนดเงื่อนไข
หรือถ้าตั้งชื่อไว้ก็ใส่เป็นชื่อได้
แล้วหลังวงเล็บก็เป็นรูปแบบที่ต้องการให้ทำเมื่อมีตัวนั้นอยู่ จากนั้นคั่นด้วย |
แล้วก็ตามด้วยรูปแบบเมื่อไม่มี
เพียงแต่ว่ากรณีที่ไม่ใส่รูปแบบเมื่อไม่มี จะละ | ไปเลยก็ได้
ใส่แค่รูปแบบเมื่อมีอย่างเดียวเฉยๆต่อจากวงเล็บ
อย่างไรก็ตาม การเขียนแบบนี้
ใช้ในจาวาสคริปต์ไม่ได้ แต่ใช้ได้ในไพธอน, รูบี
และ php
ตัวอย่าง เช่น หากต้องการหาคำที่เป็นพยัญชนะตัวเดียวประกอบกับสระ "เ" หรือ "า"
หรือ "ะ" ในจำนวนนี้มีสระ "เ" ที่ต้องวางอยู่ด้านหน้า ที่เหลืออยู่หลัง
และบางครั้งก็อาจมีทั้งคู่ เช่น "เอะ" หมายความว่าด้านหน้าพยัญชนะอาจมีสระ "เ"
หรือไม่ก็ได้ และด้านหลังจะมี "า" หรือ "ะ" อยู่หรือไม่ก็ได้
ดังนั้นอาจเขียนได้เป็น
คำค้น |
ข้อความ | ผลการค้น เบ บะ เบะ บา เบา บ เบาะ |
กลุ่มคำที่เข้าข่าย เบบะเบะบาเบาบเบาะ |
แต่พอเขียนแบบนี้จะเห็นว่าแค่ "บ" ตัวเดียวซึ่งไม่มีทั้ง "เ" ตามหน้าและ "าะ"
ตามหลังเลยก็เข้าข่ายด้วย ถ้าหากเราไม่ต้องการก็ต้องตั้งเงื่อนไขว่าถ้าไม่มี "เ"
นำหน้าจะต้องมี "า" หรือ "ะ" ตัวใดตัวหนึ่งตามหลัง แต่ถ้ามี "เ" นำหน้าแล้ว จะมี
"า" และ "ะ" ตามหลังหรือไม่ก็ได้ ซึ่งจะเขียนได้ดังนี้
คำค้น |
ข้อความ | ผลการค้น (ใน python, ruby, php) เบ บะ เบะ บา เบา บ เบาะ |
กลุ่มคำที่เข้าข่าย เบบะเบะบาเบาเบาะ |
ในที่นี้ (1) แทนกลุ่ม 1 ซึ่งอาจมีสระ เ หรือไม่มีอะไรอยู่ก็ได้
และการพิจารณาส่วนด้านขวาก็จะต่างกันไป
โครงสร้างการเขียนค่อนข้างซับซ้อนดูแล้วเข้าใจยาก งงได้ง่าย
จึงต้องค่อยๆพยายามทำความเข้าใจให้ดี
การกำหนดทางเลือกให้เข้าข่ายหลายตัว (ใช้ |)
บางครั้งเรามีรูปแบบที่ต้องการให้เข้าข่ายอยู่พร้อมกันหลายๆชุด
ซึ่งอาจจะมีลักษณะบางอย่างร่วมกันบ้างหรือไม่มีเลย
กรณีแบบนี้สามารถเขียนรูปแบบทั้งหมดที่ต้องการแล้วคั่นด้วย |
ตัวอย่าง เมื่อต้องการให้รูปแบบเป็น bcd หรือ efg
คำค้น |
ข้อความ | ผลการค้น bcd efg hij klm |
กลุ่มคำที่เข้าข่าย bcdefg |
หรือเช่นต้องการอักษร ๓ ตัวที่เป็นตัวเลขสลับกับตัวหนังสือ
คำค้น |
ข้อความ | ผลการค้น 1a1 2aa e3a 2b2 ddd e33 de2 |
กลุ่มคำที่เข้าข่าย 1a1e3a2b2 |
ปกติถ้าไม่มีวงเล็บโค้ง () อยู่ | จะเป็นการแบ่งกั้นรูปแบบออกเป็น ๒ ส่วน
แต่ผลของ | นั้นสามารถแบ่งคั่นได้ด้วยวงเล็บ ()
หากต้องการของเขตของการแบ่งแค่ตรงไหนก็ใช้ () ล้อมส่วนนั้น
ตัวอย่าง
คำค้น |
ข้อความ | ผลการค้น il fiore la foglia il seme la radice |
กลุ่มคำที่เข้าข่าย il fiorela fogliail semela radice |
พื้นฐานการใช้ regex โดยคร่าวๆก็มีอยู่ราวๆนี้
ที่เหลือก็เป็นรายละเอียดปลีกย่อยที่อาจต่างกันไปในแต่ละภาษา
ซึ่งมีอะไรให้ต้องเรียนรู้กันต่อไป
ที่สำคัญคือแค่อ่านจบตรงนี้ไปคงยังไม่อาจเข้าใจและจำได้ทั้งหมด
ต้องหาโอกาสใช้บ่อยๆจึงจะเร่ิมค่อยๆจำได้ไปเอง
สำหรับคนที่ต้องการใช้ในภาษาไพธอนให้อ่านเพิ่มเติมได้ใน
https://phyblas.hinaboshi.com/20160922
อ้างอิง