φυβλαςのβλογ
phyblas的博客



การใช้ regular expression (regex) ใน python
เขียนเมื่อ 2016/09/22 02:03
การวิเคราะห์ตัวหนังสือหรือข้อความเป็นงานอย่างหนึ่งที่สามารถทำได้โดยอาศัยการเขียนโปรแกรมเพื่อช่วยจัดการ

ในการเขียนโปรแกรมวิเคราะห์ข้อความนั้น มีเทคนิคหนึ่งที่ควรจะรู้เพราะเป็นประโยชน์เป็นอย่างมากนั่นคือสิ่งที่เรียกว่า เรกูลาร์ เอ็กซ์เพรชชัน (regular expression)

เนื่องจากชื่อยาวจึงมักจะถูกเรียกย่อๆว่า regex หรือบางทีก็สั้นๆเป็น re และในภาษาไทยบางครั้งก็อาจแปลว่า "นิพจน์ปกติ"

regex เป็นรูปแบบการเขียนที่นิยมใช้กันทั่วไปในการแสดงรูปแบบของตัวหนังสือ

หากใช้ regex แล้วจะทำให้สามารถค้นหากลุ่มตัวหนังสือที่มีรูปแบบตามที่ต้องการจากข้อความหรือกลุ่มตัวอักษรได้

ภาษาโปรแกรมต่างๆส่วนใหญ่ได้บรรจุคำสั่งสำหรับใช้งาน regex เอาไว้ แม้แต่ละภาษาจะมีไวยากรณ์ที่แตกต่างกัน แต่รูปแบบของ regex นั้นเหมือนกันทั้งหมด แม้จะมีต่างกันไปบ้างเล็กน้อย

ในบทความนี้จะอธิบายการใช้งาน regex ในภาษาไพธอนเป็นหลัก

สำหรับคนที่ใช้ภาษาอื่นแนะนำให้อ่านบทความหน้านี้ https://phyblas.hinaboshi.com/20190709



ในภาษาไพธอนมีมอดูล (ไลบรารี) ที่ใช้สำหรับจัดการกับ regex โดยเฉพาะอยู่ ทำให้สามารถใช้ regex ได้อย่างง่ายดาย

มอดูลนั้นชื่อก็ตรงตัวสั้นๆ นั่นคือ re

เช่นเดียวกับมอดูลอื่นๆในไพธอน ก่อนจะใช้ก็ต้องทำการ import เพื่อเรียกใช้ก่อน
import re



ตัวอย่างปัญหาที่ควรใช้ regex

เพื่อให้เข้าใจความหมายและเห็นประโยชน์ขอเริ่มจากยกตัวอย่างสิ่งที่ทำให้การใช้ regex มีความจำเป็น

ยกตัวอย่างเช่นเรามีสายอักขระอยู่อันหนึ่งที่ประกอบไปด้วยตัวเลขและตัวอักษรโรมันปนกัน
'gh3r0v1o6mng70yc89z09vippim0e1yn2v7koghojgjed3wq2b10ul8i8l'

หากต้องการค้นหาว่ามีตัวเลขอะไรบ้างอยู่ภายในนี้จะทำอย่างไร?

สายอักขระในไพธอนมีเมธอด index() ไว้ค้นหาข้อความที่ต้องการที่อยู่ข้างในได้ แต่ว่าหาได้ทีละตัวเท่านั้น เช่น s.index('3') จะได้ 2 แต่ว่าตัวเลขมีตั้งแต่ 0 ถึง 9 ถ้าใช้วิธีนี้ก็จะต้องมาไล่ค้นทีละตัว ไม่สะดวก

ตรงจุดนี้หากใช้ regex ช่วยก็จะสามารถค้นตัวเลขทั้งหมดได้อย่างง่ายด้วยการเขียนโค้ดแค่สั้นๆ ดังที่จะอธิบายต่อไป



การค้นหาคัดกรองตัวเลขออกจากตัวหนังสืออื่นๆ (ใช้ \d และ \D)

มอดูล re ในไพธอนประกอบไปด้วยหลายฟังก์ชันด้วยกัน แต่ในเบื้องต้นนี้จะขอยกมาใช้แค่ฟังก์ชันเดียวซึ่งเข้าใจง่ายที่สุดมาใช้ เป็นตัวอย่างทั้งหมด นั่นคือ re.findall()

ฟังก์ชันนี้จะทำการหาส่วนประกอบที่เข้ารูปแบบตามที่ต้องการจากภายในสายอักขระออกมาแสดงเป็นลิสต์

รูปแบบการใช้คือ
re.findall(p,s)

โดยที่ p คือรูปแบบของ regex ที่ต้องการค้น ส่วน s คือสายอักขระที่ต้องการค้น

รูปแบบการค้นที่ว่านั้นคือข้อความที่เขียนด้วยภาษาเฉพาะของ regex ซึ่งเป็นเรื่องที่มีรายละเอียดต้องจำเยอะพอสมควร

ตอนนี้จะขอยกตัวอย่างง่ายๆ นั่นคือ \d

ใน regex นั้นสัญลักษณ์ \d จะแทนอักษรที่ตัวเลขใดๆตั้งแต่ 0 ถึง 9 ดังนั้นหากต้องการหาตัวเลขใดๆก็แค่กำหนดรูปแบบการค้นเป็น '\d'

ดังนั้นเราลองเอาสายอักขระที่ยกมาข้างต้นมาใช้แล้วลองค้นด้วย '\d' ดูได้เลย
s = 'gh3r0v1o6mng70yc89z09vippim0e1yn2v7koghojgjed3wq2b10ul8i8l' # ข้อความที่ต้องการค้น
p = '\d' # รูปแบบการค้น
r = re.findall(p,s) # ให้ผลลัพธ์การค้นเก็บไว้ในตัวแปร r
print(r) # ได้ ['3', '0', '1', '6', '7', '0', '8', '9', '0', '9', '0', '1', '2', '7', '3', '2', '1', '0', '8', '8']

จะเห็นว่าผลที่ได้ก็คือตัวเลขทั้งหมดที่อยู่ภายในนี้โดยเรียงตามลำดับ

หากต้องการเฉพาะเลขที่ติดกัน ๒ ตัวก็เขียนเป็น '\d\d' เช่น
r = re.findall('\d\d',s)
print(r) # ได้ ['70', '89', '09', '10']

นอกจาก \d ซึ่งแทนตัวเลขแล้วยังมีรูปแบบอื่นๆอีกมากมายซึ่งก็มักเขียนแทนด้วยแบ็กสแลช (\) แบบนี้ เช่น \D จะแทนอะไรก็ตามที่ไม่ใช่ตัวเลข

ตัวอย่าง
r = re.findall('\D',s)
print(r) # ได้ ['g', 'h', 'r', 'v', 'o', 'm', 'n', 'g', 'y', 'c', 'z', 'v', 'i', 'p', 'p', 'i', 'm', 'e', 'y', 'n', 'v', 'k', 'o', 'g', 'h', 'o', 'j', 'g', 'j', 'e', 'd', 'w', 'q', 'b', 'u', 'l', 'i', 'l']

ผลที่ได้จะตรงข้ามกับ \d คือกลายเป็นได้อักษรทั้งหมดที่ไม่ใช่ตัวเลข

ลองหาที่ติดกัน ๓ ตัวดูก็ได้เช่นกัน
r = re.findall('\D\D\D',s)
print(r) # ได้ ['mng', 'vip', 'pim', 'kog', 'hoj', 'gje']

และหากต้องการค้นหาที่เป็นตัวเลขตามด้วยที่ไม่ใช่ตัวเลขก็ใช้ \d กับ \D คู่กัน เป็น
r = re.findall('\d\D',s)
print(r) # ได้ ['3r', '0v', '1o', '6m', '0y', '9z', '9v', '0e', '1y', '2v', '7k', '3w', '2b', '0u', '8i', '8l']



สัญลักษณ์แทนตัวอักษรชนิดต่างๆ

ในตัวอย่างที่แล้วได้ยก \d และ \D มาเป็นตัวอย่าง แต่ว่านอกจากนี้ยังมีอักษรอีกหลายรูปแบบ สรุปได้ดังตารางนี้

\d ตัวเลข 0-9
\D ตัวอื่นนอกจากตัวเลข 0-9
\t แท็บ
\n ขึ้นบรรทัดใหม่
\s สเปซบาร์หรือแท็บหรือขึ้นบรรทัดใหม่
\S ตัวอื่นนอกจากสเปซบาร์หรือแท็บหรือขึ้นบรรทัดใหม่
\w ตัวเลขและอักษรที่ใช้สร้างคำในภาษาต่างๆ รวมถึงขีดล่าง (_) ไม่รวมสัญลักษณ์อื่นๆ
\W ตัวอื่นที่ไม่ใช่ \w
. (จุด) แทนตัวอักษรอะไรก็ได้

จะเห็นว่ามีการแยกตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก โดยที่ตัวพิมพ์ใหญ่เช่น \D \S \W จะมีความหมายตรงกันข้ามกับตัวพิมพ์เล็ก \d \s \w ต้องแยกใช้ให้ดี

\s จะแทนตัวอักษรเว้นวรรคหนึ่งตัว นั่นคือสเปซบาร์ ( ) และแท็บ (\t, คือการเคาะเว้นย่อหน้า) รวมถึงการขึ้นบรรทัดใหม่ (\n)

ตัวอย่าง เช่น หาส่วนประกอบที่เป็นตัวหนังสือที่ไม่ใช่ตัวเลขสองตัวซึ่งคั่นด้วยช่องว่าง
s = 'In ciascuna epoca, il pastore compare per sconfiggere le tenebre'
r = re.findall('\D\s\D',s)
print(r) # ได้ ['n c', 'a e', ', i', 'l p', 'e c', 'e p', 'r s', 'e l', 'e t']

ที่จริงตัวอย่างนี้จะใช้ช่องว่าง ' ' แทน \s นั่นคือ p = '\D \D' ก็ได้ผลเช่นเดียวกัน (ช่องว่างก็นับเป็นอักษรตัวหนึ่ง)

แต่ \s นั้นจะรวมแท็บและการขึ้นบรรทัดใหม่ (\n) ด้วย ตัวอย่างเช่น
s = '''Tuttavia
quando la pace viene risbalita,
scompare'''

r = re.findall('\D\s\D',s)
print(r) # ได้ ['a\nq', 'o l', 'a p', 'e v', 'e r', ',\ns']

ส่วน \w จะแทนตัวอักษรสำหรับสร้างคำในภาษาต่างๆ ไม่รวมพวกเครื่องหมายต่างๆ มีแค่ขีดล่าง _ ที่นับรวม
s = '555 !!! ฮาฮาฮา hahaha ๕๕๕ ははは 哈哈哈 ?&^ H-H_H-'
r = re.findall('\w\w\w',s)
print(r) # ได้ ['555', 'ฮาฮ', 'าฮา', 'hah', 'aha', '๕๕๕', 'ははは', '哈哈哈', 'H_H']

อนึ่ง ความหมายของ \w จะต่างออกไปเมื่อสายอักขระเป็นชนิด ASCII แทนที่จะเป็นยูนิโค้ด โดย \w จะรวมแค่อักษรโรมัน ๒๖ ตัวทั้งพิมพ์เล็กใหญ่ และขีดล่าง _ (A-Z, a-z, 0-9, _) เท่านั้น

และหากต้องการให้อักษรตัวหนึ่งแทนอะไรก็ได้ ก็ให้ใช้ . (จุด)

ตัวอย่าง หาคำที่เป็น de ตามด้วยอะไรก็ได้อีก ๓ ตัว
s = 'del dal della dalla dei dai degli dagli delle dalle dello dallo'
r = re.findall('de...',s)
print(r) # ได้ ['del d', 'della', 'dei d', 'degli', 'delle', 'dello']

เพียงแต่ว่ากรณีที่ต้องการจะค้นหาอักษรจุดจริงๆจะต้องใช้ \ นำหน้ากลายเป็น \. แบบนี้ ไม่เช่นนั้นจะกลายเป็นการหาตัวอะไรก็ได้ไป

ตัวอย่าง
s = 'a. a, a; a:'
r = re.findall('a.',s)
print(r) # ได้ ['a.', 'a,', 'a;', 'a:']
r = re.findall('a\.',s)
print(r) # ได้ ['a.']

ไม่ใช่แแค่จุดเท่านั้น มีเครื่องหมายอีกหลายตัวที่ทำหน้าที่พิเศษ เช่น ()[]{}|+*?\^$ หากต้องการค้นอักษรพวกนี้จริงๆจำเป็นต้องใส่ \ นำหน้า แม้แต่ตัว \ เองก็ด้วย



ใช้สายอักขระดิบเอาไว้ก่อนจะสบายใจกว่า (ใส่ r หน้าเครื่องหมายคำพูด)

เนื่องจากใน regex มักประกอบด้วยแบ็กสแลช (\) แต่ว่าแบ็กสแลชนั้นก็ถูกใช้เป็นเอสเค็ปคาแร็กเตอร์ในภาษาไพธอนอยู่ด้วย ดังนั้นอาจเกิดการซ้ำซ้อนกันทำให้เกิดข้อผิดพลาดที่ไม่คาดคิดขึ้นมาได้

เช่น ตัวแบ็กสแลชเองนั้นเอาไว้นำหน้าตัวอักษรเพื่อแทนอะไรที่มีความหมายพิเศษ แต่เมื่อต้องการใช้ตัวอักษร \ ขึ้นมาจริงๆจะต้องใส่ \ นำหน้าอีกตัวกลายเป็น \\

นั่นทำให้ในภาษาไพธอนนั้นเวลาที่ต้องการให้เป็น \ เพื่อเป็นสัญลักษณ์พิเศษใน regex จะต้องเขียนเป็น regex และเวลาที่ต้องการใช้อักษร \ จริงๆจะต้องเขียนเป็น \\\\ ซึ่งดูแล้วยืดยาว

การแก้ปัญหาก็คือให้เขียนในรูปของสายอักขระดิบ โดยการเติม r นำหน้า

ตัวอย่าง
s = r'\_/ ~/-\ \.~!'
r = re.findall('\\S',s)
print(r) # ได้ ['\\', '_', '/', '~', '/', '-', '\\', '\\', '.', '~', '!']
r = re.findall(r'\S',s)
print(r) # ได้ ['\\', '_', '/', '~', '/', '-', '\\', '\\', '.', '~', '!']
r = re.findall('\\\\\S',s)
print(r) # ได้ ['\\_', '\\.']
r = re.findall(r'\\\S',s)
print(r) # ได้ ['\\_', '\\.']

ฉะนั้นแล้วโดยทั่วไปสายอักขระที่ใช้กำหนดรูปแบบของ regex ในภาษาไพธอนจึงมักนิยมเขียน r นำหน้าให้เป็นสายอักขระดิบเอาไว้ก่อนจะได้ใช้ \ ได้อย่างสบายใจ



ข้อควรระวังเรื่องยูนิโค้ด (สำหรับไพธอน 2)

ในไพธอน 2 สายอักขระทั่วไปจะเป็น ASCII ทำให้เมื่อมีการใช้อักษรที่นอกเหนือจาก ASCII เช่นตัวอักษรภาษาไทยจะมีปัญหาได้ง่ายแม้ว่าจะใช้ได้ก็ตาม เวลาที่ใช้ regex ก็จะไม่ได้ผลตามที่ต้องการ เนื่องจากอักษรที่ไม่ใช่ ASCII จะถูกมองเป็นอักษรที่ยาวกว่าหนึ่งหน่วยทำให้เกิดผลลัพธ์ที่ไม่คาดคิดได้

ผลที่ได้จะออกมาผิดพลาดอย่างไรนั้นในที่นี้จะไม่ขอเน้นรายละเอียดให้ไปลองดู กันเองได้ จะเน้นแค่ว่าในไพธอน 2 หากใช้อักษรไทยควรใส่ u นำหน้าเพื่อให้เป็นยูนิโค้ดทั้งหมดเสมอ ปัญหาก็จะหมดไป (ส่วนไพธอน 3 สายอักขระเป็นยูนิโค้ดอยู่แล้วไม่ต้องใส่ u ก็ได้)

และ u นั้นสามารถใส่รวมกับ r ซึ่งกล่าวถึงไปแล้วข้างต้นได้ โดยเขียนเป็น ur จะได้เป็นสายอักขระดิบที่เป็นยูนิโค้ด

ตัวอย่าง (สำหรับไพธอน 2 เท่านั้น)
r = re.findall(ur'ก\D\S.',u'ไก่จิกเด็กโข่งบนปากโอ่ง')
print(' | '.join(r)) # ได้ ก่จิ | กเด็ | กโข่ | กโอ่

เพียงแต่ว่า ur นั้นไม่สามารถใช้ในไพธอน 3 ได้ ใช้ได้แค่ r หรือ u ตัวใดตัวหนึ่งเท่านั้น

บทความนี้เน้นไพธอน 3 เป็นหลักมากกว่าดังนั้นตัวอย่างต่อไปนี้แม้จะใส่อักษรไทยด้วยก็จะละไม่ใส่ u แต่คนที่ใช้ไพธอน 2 ก็แค่จะต้องเติมตัว u เข้ามา

เกี่ยวกับความต่างเรื่องสายอักขระระหว่างไพธอน 2 และ 3 มีเขียนเอาไว้ในนี้ https://phyblas.hinaboshi.com/20151219 อ่านเพิ่มเติมกันได้

นอกจากนี้แล้ว ความหมายของ \w กับ \W สำหรับสายอักขระที่เป็นยูนิโค้ดกับ ASCII ก็ต่างกันด้วย ดังที่ได้กล่าวถึงไปแล้ว จึงต้องระวังตรงจุดนี้ด้วย



การกำหนดชุดตัวอักษรที่เข้าข่ายตามที่ต้องการ (ใช้วงเล็บเหลี่ยม [ ])

กลุ่มตัวอักษรชนิดที่กำหนดด้วยแบ็กสแลชนั้นเป็นการแบ่งกลุ่มแบบคร่าวๆ แต่บ่อยครั้งที่เราอาจต้องการเจาะจงอักษรบางกลุ่ม

การกำหนดกลุ่มตัวอักษรตามที่ต้องการทำได้โดยใช้วงเล็บเหลี่ยมล้อม [] แล้วใส่อักษรที่ต้องการทั้งหมดในนั้น

แต่ว่าหากมีอักษรหลายตัวที่ต้องการให้เข้าข่ายก็จะต้องเขียนไล่ไปทั้งหมด เช่นต้องการ a ถึง g ก็ต้องพิมพ์ [abcdefg] แบบนี้ดูแล้วค่อนข้างยาว

สำหรับกลุ่มตัวอักษรที่มีลำดับติดกันแบบนี้เพื่อความสะดวกง่ายขึ้นในส่วนนี้มีตัว ช่วย นั่นคือใช้เครื่องหมาย - เพื่อแสดงช่วง เช่น ถ้าใส่ [a-y] หมายถึงอักษรตั้งแต่ a ถึง y [ก-ช] หมายถึงอักษรตั้งแต่ ก ถึง ช เป็นต้น

ลำดับอักษรในที่นี้เป็นลำดับที่เรียงตามเลขในยูนิโค้ด สำหรับภาษาไทยแล้วอักษรตัวแรกสุดคือ "ก" และตัวสุดท้ายคือเลข "๙" ดังนั้นหากต้องการแสดงถึงอักษรไทยทั้งหมดก็เขียนเป็น [ก-๙]

หากเขียน [ก-ฮ] จะเท่ากับ [กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮ] นั่นคือพยัญชนะทั้ง ๔๔ ตัว รวม "ฤ" กับ "ฦ" ด้วย

สำหรับอักษรจีนจะใช้ [一-龥] เพื่อครอบคลุมทุกตัวอักษร ส่วนอักษรญี่ปุ่นฮิรางานะใช้ [ぁ-ゞ] และคาตาคานะใช้ [ァ-ヶ]

อักษร - ถือเป็นอักษรพิเศษในกรณีนี้ ไม่ได้ถูกตีความเปํนอักษรตัวหนึ่ง เช่น [ค-ญ] ไม่ได้หมายถึงอักษร ค หรือ - หรือ ญ แต่หมายถึงอักษรตั้งแต่ ค ถึง ญ

แต่หากต้องการให้ - รวมอยู่ในกลุ่มที่เข้าข่ายด้วยก็ให้วางไว้เป็นตัวแรก เพราะหากวางไว้ต่อจากตัวอักษรอื่นจะกลายเป็นการกำหนดช่วงตั้งแต่อักษรตัวนั้นไปจนถึงอักษรที่อยู่ทางขวา

ตัวอย่าง
s = '1+2 3-4 5×6 7÷8 ~~~**'
r = re.findall(r'\d[+-÷]\d',s)
print(r) # ได้ ['1+2', '3-4', '5×6', '7÷8'] (ทั้งๆที่ไม่ได้ใส่ × มาด้วย)
r = re.findall(r'\d[-+÷]\d',s)
print(r) # ได้ ['1+2', '3-4', '7÷8']
r = re.findall(r'\d[+-*×]\d',s)
# ได้ error: bad character range +-*

ในตัวอย่างแรกที่มี × โผล่มาด้วยเพราะ × อยู่ระหว่าง + กับ ÷ ส่วนตัวอย่างสุดท้ายที่ผิดพลาดเพราะอักษร * มาก่อน +

ภายในวงเล็บเหลี่ยม [ ] นั้นต่อให้ใส่อักษรลงไปกี่ตัวก็ตามทั้งหมดก็แทนอักษรแค่ตัวเดียวเท่านั้น เช่น [0-9] มีค่าเท่ากับ \d ถ้าหากต้องการให้เป็นหลายตัวก็คือต้องพิมพ์วงเล็บแบบเดิมซ้ำ

หากมี ^ อยู่เป็นตัวอักษรแรกสุดภายในวงเล็บเหลี่ยมผลที่ได้จะเป็นตรงกันข้าม นั่นคือเอาอักษรทุกตัวยกเว้นที่ระบุไว้ในนั้น

ตัวอย่าง
s = 'bakadana'
r = re.findall(r'[^bk]a',s)
print(r) # ได้ ['da', 'na']
r = re.findall(r'[^l-z]a',s)
print(r) # ได้ ['ba', 'ka', 'da']

หากต้องการให้อักษร ^ เองนั้นอยู่ในกลุ่มที่เข้าข่ายก็ให้วางไว้ในตำแหน่งไหนก็ได้ที่ไม่ใช่ตัวแรกสุด แบบนั้นก็จะถูกตีความเป็นอักษรตัวหนึ่งธรรมดาไป



การกำหนดให้อักษรมีกี่ตัวก็ได้ (ใช้ +)

หากมีอักษรที่ต้องการให้มีแต่ไม่ได้เจาะจงว่าจะต้องมีกี่ตัว จะมีหนึ่งตัวหรือกี่ตัวก็ได้ กรณีแบบนี้ให้เติม + ตามหลังตัวอักษรที่ต้องการ เช่น
r = re.findall(r'a\d+','a12 ab21 ba324 dfa7777')
print(r) # ได้ ['a12', 'a324', 'a7777']

กรณีที่เป็นชุดอักษรที่กำหนดด้วยกรอบ [] ก็ใส่ + ได้เช่นกัน เช่น ลองหาอักษรที่เป็นพยัญชนะ (ก-ฮ) ที่อยู่ติดกัน
r = re.findall(r'[ก-ฮ]+','กากมากย่อยยาก')
print(r)  # ['ก', 'กม', 'กย', 'อยย', 'ก']

แบบนี้จะเห็นว่าพยัญชนะอะไรก็ได้ที่อยู่ติดกันก็จะรวมอยู่ในกลุ่มเดียวกัน



การกำหนดให้อักษรมีหรือไม่มีก็ได้ (ใช้ ? และ *)

หากเติมเครื่องหมายคำถาม ? ลงข้างหลังตัวอักษรจะหมายความว่าอักษรตัวนั้นจะมีหรือไม่มีอยู่ก็ได้

ตัวอย่าง
r = re.findall(r'c\d?','c1 c c36 cc')
print(r) # ได้ ['c1', 'c', 'c3', 'c', 'c']

และถ้าใช้ดอกจัน * จะหมายถึงว่าจะมีหรือไม่มีก็ได้และถ้ามีจะมีกี่ตัวก็ได้
r = re.findall(r'ค\d*','ค ค39 ค1 ค4567 ก9 คค0')
print(r) # ได้ ['ค', 'ค39', 'ค1', 'ค4567', 'ค', 'ค0']



การกำหนดให้อักษรมีจำนวนตามที่กำหนด (ใช้วงเล็บปีกกา { })

ปกติแล้วต้องการให้มีอักษรกี่ตัวก็ต้องเขียนอักษรไปเป็นจำนวนเท่านั้น เช่นตัวเลข ๔ ตัวก็เขียน \d\d\d\d แต่ว่าหากมีจำนวนมากการเขียนแบบนี้จะยาว

การใช้วงเล็บปีกกาจะช่วยให้การเขียนสั้นลงได้ โดยเขียนตัวที่ต้องการซ้ำแล้วตามด้วยวงเล็บปีกกาที่คร่อมด้วยจำนวนที่ต้องการ

ตัวอย่าง ตัวเลขยาว ๓ ตัว
r = re.findall(r'\d{3}','123x456x789x00')
# เหมือนกับ '\d\d\d'
print(r) # ได้ ['123', '456', '789']

แต่บางครั้งจำนวนก็อาจไม่ได้รู้แน่ชัดแต่มีขอบเขตที่แน่นอนอยู่ค่าหนึ่ง แบบนั้นก็สามารถใส่จุลภาค , ไว้ใน {} โดยจำนวนที่อยู่ทางซ้าย , คือขอบเขตล่าง ถ้าไม่ใส่คือ 0 ทางขวา , คือขอบเขตบน ถ้าไม่ใส่คือไม่จำกัด
\d{2,3} เท่ากับ \d\d\d? คือตัวเลข ๒ ถึง ๓ ตัว
\d{,3} เท่ากับ \d{0,3} หรือ \d?\d?\d? คือตัวเลขไม่เกิน ๓ ตัว
\d{2,} เท่ากับ \d\d+ หรือ \d\d\d* คือตัวเลข ๒ ตัวขึ้นไป

ตัวอย่าง หาเลขโทรศัพท์ ซึ่งควรจะขึ้นต้นด้วย 0 แล้วมีความยาว ๙ ถึง ๑๐ ตัว
s = '023456789 0897654321 01234567 123456789'
r = re.findall(r'0\d{8,9}',s)
print(r) # ได้ ['023456789', '0897654321']



โลภมากหรือไม่โลภมาก (ใช้ ?)

ปกติแล้วเวลาที่ใช้ + หรือ * นั้นจะมีอักษรถูกรวมอยู่ในกลุ่มกี่ตัวก็เป็นไปได้ ซึ่งในบางครั้งก็ทำให้เกิดความคลุมเครือว่าต้องการกี่ตัวกันแน่ และทำให้เกิดผลที่ไม่ได้คาดหวัง

ยกตัวอย่างเช่นถ้าเราต้องการค้นหาคำอะไรก็ได้ยาวแค่ไหนก็ได้ที่ลงท้ายด้วยสระ "า" ก็อาจเขียนเป็น '\S+า' เช่น
r = re.findall(r'\S+า','พลังคลื่นเต่าสะท้านฟ้า!')
print(r) # ได้ ['พลังคลื่นเต่าสะท้านฟ้า']

จะเห็นว่าพอเขียนแบบนี้แล้ว \S+ จะแทนตัวอักษรตั้งแต่ตัวแรกจนถึงก่อน "า" ตัวสุดท้าย แต่ในความเป็นจริงก็มี "า" นำหน้าอยู่ก่อนตั้ง ๒ ตัวซึ่งถ้าจะนับรวมถึงแค่ "า" ตัวแรกก็ยังถือว่าเข้าข่ายรูปแบบที่ต้องการอยู่ดี แต่ว่าโดยทั่วไปแล้วโปรแกรมจะพยายามหากลุ่มอักษรที่เข้าข่ายให้ยาวที่สุดดัง นั้นต่อให้เจออักษรที่เข้าข่าวตามที่ต้องการแล้วหากไล่ตัวต่อไปดูแล้วยัง เข้าข่ายอยู่มันก็จะนับต่อไปจนสุด ลักษณะแบบนี้เรียกว่าเป็นการจับกลุ่มแบบ "โลภมาก"

แต่เราสามารถทำให้โปรแกรมหยุดหาต่อทันทีที่เจอกลุ่มตัวอักษรที่เข้าข่ายครบในขั้นต่ำ ซึ่งทำได้โดยการเติม ? ลงไปต่อท้าย เช่น
r = re.findall(r'\S+?า','พลังคลื่นเต่าสะท้านฟ้า!')
print(r) # ได้ ['พลังคลื่นเต่า', 'สะท้า', 'นฟ้า']

ลักษณะแบบนี้เรียกว่าเป็นการจับกลุ่มแบบ "ไม่โลภมาก" จะเป็นแบบโลภมากหรือไม่นั้นต่างกันแค่เติม ? ต่อท้ายหรือไม่เท่านั้น

? ในที่นี้มีความหมายต่างจาก ? ที่ตามหลังตัวอักษรทั่วไปเพื่อแทนการมีหรือไม่มีก็ได้ของตัวนั้น และมันสามารถตามหลัง + หรือตามหลัง * หรือ {} หรือแม้แต่ ? เองก็ได้

ตัวอย่างอื่นๆ
r = re.findall(r'ก{2,5}','กกกกกกกกก')
print(r) # ได้ ['กกกกก', 'กกกก']
r = re.findall(r'ก{2,5}?','กกกกกกกกก')
print(r) # ได้ ['กก', 'กก', 'กก', 'กก']
s = 'ปลาทู-ปลาเก๋า-ปลากระพง-ปราจีนบุรี'
r = re.findall(r'ปลา[ก-๙]*',s)
print(r) # ได้ ['ปลาทู', 'ปลาเก๋า', 'ปลากระพง']
r = re.findall(r'ปลา[ก-๙]*?',s)
print(r) # ได้ ['ปลา', 'ปลา', 'ปลา']

กรณีที่ regex ทั้งหมดมีแต่ส่วนที่ใช้ * หรือ ? นั้นจำนวนอักษรขั้นต่ำคือ 0 หมายความว่าถึงไม่มีเลยก็นับ ซึ่งอาจชวนให้เป็นห่วงว่าเวลาค้นแบบไม่โลภมาก (เติม ?) จะได้สายอักขระว่าง "" เป็นจำนวนไม่สิ้นสุด แต่ในความเป็นจริงแม้จะไม่นับเลยก็ยังไล่ไปยังอักษรตัวถัดไป ดังนั้นจึงไม่มีปัญหา
r = re.findall(r'5*','5555')
print(r) # ได้ ['5555', '']
r = re.findall(r'5*?','5555')
print(r) # ได้ ['', '', '', '', '']
r = re.findall(r'l?a?','lahllala')
print(r) # ได้ ['la', '', 'l', 'la', 'la', '']
r = re.findall(r'l??a??','lahllala')
print(r) # ได้ ['', '', '', '', '', '', '', '']



การคัดกรองให้เข้าข่ายเฉพาะเริ่มต้นและปิดท้ายสายอักขระ (ใช้ ^ และ $)

หากต้องการให้เข้าข่ายแค่เฉพาะเมื่อคำนั้นอยู่ที่ตำแหน่งแรกของสายอักขระเท่านั้นให้ใส่ ^ นำหน้า

และหากต้องการให้เข้าข่ายแค่เฉพาะเมื่อคำนั้นอยู่ที่ตำแหน่งท้ายสุดก็ใส่ $ ต่อท้าย ตัวอย่างเช่น
r = re.findall(r'^s\w+','saa shhh')
print(r) # ได้ ['saa']
r = re.findall(r's\w+$','saa shhh')
print(r) # ได้ ['shhh']



การคัดกรองให้เข้าข่ายเฉพาะเมื่ออยู่ต้นหรือท้ายคำ (ใช้ \b)

^ กับ $ นั้นจะใช้กรณีที่คัดคำที่อยู่ต้นหรือท้ายของทั้งสายอักขระเท่านั้น กรณีที่ต้องการคัดเอาเฉพาะคำที่แค่อยู่ต้นหรือท้ายคำแต่ไม่ใช่ต้นหรือท้ายของทั้งสายอักขระ แบบนี้จะใช้ \b

ต้นและท้ายคำในที่นี้สิ่งที่เป็นตัวแบ่งก็คือ
- ช่องว่าง
- ขึ้นบรรทัดใหม่
- เริ่มต้นและลงท้ายสายอักขระ
- พวกเครื่องหมายต่างๆเช่น ,./?!\<>[]{}()*&^%$#@~ ยกเว้นแค่ _

หากวาง \b ไว้หน้าคำ จะเข้าข่ายเมื่อมีกลุ่มตัวอักษรสำหรับสร้างคำในภาษาต่างๆอยู่ต่อจากตัวแบ่ง

หากวาง \b ไว้หลังคำ จะเข้าข่ายเมื่อกลุ่มตัวอักษรอยู่นำหน้าตัวแบ่ง

และหากวาง \b ไว้ทั้งหน้าและหลังคำ จะเข้าข่ายก็ต่อเมื่อกลุ่มตัวอักษรนั้นถูกขนาบระหว่างตัวแบ่ง

ตัวอย่าง
r = re.findall(r'[ก-ฮ]+','s กขคaง z')
print(r) # ได้ ['กขค', 'ง']
r = re.findall(r'\b[ก-ฮ]+','s กขคaง z')
print(r) # ได้ ['กขค']
r = re.findall(r'[ก-ฮ]+\b','s กขคaง z')
print(r) # ได้ ['ง']
r = re.findall(r'\b[ก-ฮ]+\b','s กขคaง z')
print(r) # ได้ []

เครื่องหมายต่างๆเป็นตัวแบ่งได้หมด แต่ _ ไม่ได้
r = re.findall(r'\b[ก-ฮ]+\b','กขค.ง จ-ฉ+ช%ฌ&ญ')
print(r) # ได้ ['กขค', 'ง', 'จ', 'ฉ', 'ช', 'ฌ', 'ญ']
r = re.findall(r'\b[ก-ฮ]+\b','ป_พ^ม')
print(r) # ได้ ['ม']



การเลือกเอาแค่บางส่วน (ใช้วงเล็บโค้ง ( ))

บางครั้งเราอาจต้องการหากลุ่มอักษรที่เข้าข่ายที่ต้องการกลุ่มหนึ่ง แต่ไม่ได้ต้องการจะเอามันมาใช้ทั้งหมด เช่นว่า "อยากได้อักษรนี้ที่อยู่หน้าอักษรนี้" เป็นต้น ในกรณีแบบนี้เราอาจใช้วงเล็บโค้งล้อมรอบเฉพาะส่วนที่ต้องการ

ตัวอย่างเช่น เอาพยัญชนะที่อยู่หน้า "า" แต่ไม่เอา "า" ด้วย
r = re.findall(r'([ก-ฮ])า','อาตากามา')
print(r) # ได้ ['อ', 'ต', 'ก', 'ม']

สามารถใส่วงเล็บได้มากกว่าหนึ่งตัว กรณีแบบนั้นผลที่ได้จะออกมาเป็นทูเพิลของผลในแต่ละกลุ่มก้อน
r = re.findall(r'([ก-ฮ])า([ก-ฮ])ะ','มานะราคะซาบะ')
print(r) # ได้ [('ม', 'น'), ('ร', 'ค'), ('ซ', 'บ')]

อาจใช้เพื่อวิเคราะห์เลขทศนิยมแบ่งเป็นส่วนต่างๆได้
r = re.findall(r'(-?\d+)\.(\d*)[eE](-?\d+)','-12.3e-4 -55.41E7 1.239e2')
print(r) # ได้ [('-12', '3', '-4'), ('-55', '41', '7'), ('1', '239', '2')]



การจับกลุ่มก้อน (ใช้ (?: ))

การใส่วงเล็บนอกจากจะเป็นการแสดงว่าจะเลือกเอาเฉพาะส่วนที่อยู่ในวงเล็บแล้วยังหมายถึงการจับกลุ่มก้อนด้วย

ตัวอักษรที่จับกันเป็นกลุ่มก้อนด้วยวงเล็บจะถูกพิจารณาเหมือนเป็นตัวเดียวกัน เช่นเวลาที่ใช้ (กขค)+ แบบนี้จะหมายถึงว่ามี "กขค" ซ้ำกันกี่ตัวก็ได้

ระวังอย่าสับสนกับ [กขค] ซึ่งหมายถึงตัวใดตัวหนึ่งสักตัวจาก "กขค"

ตัวอย่าง
r = re.findall(r'(123)+\d','12312312345')
print(r) # ได้ ['123']

จะเห็นว่ามี 123 ซ้ำกันถึง ๓ ครั้งแต่ก็ถูกนับรวมอยู่ภายในกลุ่มอักษรที่เข้าข่ายกลุ่มเดียวกัน

เพียงแต่ว่าผลที่ได้แสดงแค่ 123 เพราะวงเล็บหมายถึงว่าเราจะเลือกเฉพาะแค่ส่วนนั้นด้วย ซึ่งต่อให้มีส่วนนั้นซ้ำ แต่ภายในวงเล็บถือว่ามี 123 แค่ชุดเดียว อีกทั้งเลข 4 (\d) ที่อยู่ด้่านหลังอีกตัวก็ไม่นับรวมด้วย

วิธีหนึ่งที่ใช้ได้ก็คือใช้วงเล็บครอบข้อความทั้งหมดไปด้วย หากมีวงเล็บซ้อนกัน ทั้งวงนอกและวงในจะแสดงออกมาในผลทั้งคู่ โดยวงนอกจะมาก่อน
r = re.findall(r'((123)+\d)','12312312345 123722')
print(r) # ได้ [('1231231234', '123'), ('1237', '123')]

แต่ก็มีอีกวิธีหนึ่งที่ดีกว่า นั่นคือหากเราเพียงต้องการใส่วงเล็บเพื่อต้องการจะใช้ให้พิจารณารวมเป็นกลุ่มก้อนเท่านั้น ไม่ได้ต้องการที่จะแสดงว่าจะเลือกเฉพาะตรงนั้น กรณีแบบนี้ให้เติม ?: ลงไปขึ้นต้นในวงเล็บ

ตัวอย่าง
r = re.findall(r'(?:123)+\d','12312312345 123722')
print(r) # ได้ ['1231231234', '1237']

คราวนี้จะได้กลุ่มตัวอักษรทั้งหมดตามที่แสดงไว้

หากต้องการแค่ส่วน 123 ที่ซ้ำกันตามจำนวนชุดจะใส่วงเล็บครอบซ้ำไปอีกทีก็ได้ วงเล็บวงนอกไม่มี ?: จะหมายถึงพิจารณาเอาเฉพาะส่วนนั้น
r = re.findall(r'((?:123)+)\d','12312312345 123722')
print(r) # ได้ ['123123123', '123']

ปกติแล้วหากเครื่องหมายคำถาม ? นำหน้าเป็นตัวอักษรแรกภายในวงเล็บ จะทำหน้าที่แสดงถึงความหมายพิเศษอะไรบางอย่าง โดยความหมายจะขึ้นอยู่กับตัวอักษรที่ตามมา

นอกจากโคลอน : ดังที่ได้กล่าวไปแล้วก็ยังมีตัวอื่นๆอีกเช่น ?P ?= ?! ?<= ?<! ?# เป็นต้น



การกำหนดกลุ่มคำที่มาก่อนหรือหลังคำที่ต้องการ (ใช้ (?<= ),(?<! ),(?= ),(?! ))

หากต้องการกำหนดให้คำที่ต้องการนั้นเข้าข่ายก็ต่อเมื่อนำหน้าด้วยกลุ่มคำอะไร บางอย่าง สามารถเขียนกลุ่มคำที่ต้องการนำหน้านั้นโดยคร่อมด้วย (?<= )

หรือถ้าหากต้องการให้เข้าข่ายเมื่อตามหลังกลุ่มคำอะไรบางอย่าง ก็ใช้ (?= ) คร่อมกลุ่มคำนั้น (จะหน้าหรือหลังต่างกันตรงที่มี < หรือไม่เท่านั้น ต้องแยกใช้ให้ถูก)

กลุ่มคำที่อยู่ด้านใน (?<= ) หรือ (?= ) นั้นจะไม่ถูกรวมอยู่ในกลุ่มอักษรที่จะเอา

ตัวอย่าง
r = re.findall(r'(?<=a).a','bakadana') # เอาที่ตามหลัง a
print(r) # ได้ ['ka', 'da', 'na']
r = re.findall(r'.a(?=[kdn])','bakadana') # เอาที่นำหน้า k,d,n
print(r) # ได้ ['ba', 'ka', 'da']
r = re.findall(r'(?<=a).a(?=[kdn])','bakadana') # เอาที่ตามหลัง a และนำหน้า k,d,n
print(r) # ได้ ['ka', 'da']

ในทางตรงกันข้าม หากต้องการให้เข้าข่ายเฉพาะเมื่อไม่นำหน้าหรือตามหลังกลุ่มคำอะไรบางอย่างก็ ใช้ (?! ) กับ (?<! ) ใส่กลุ่มคำนั้น ความหมายตรงข้ามกับ (?= ) กับ (?<= ) แค่เปลี่ยน = เป็น !



การนำกลุ่มก้อนมาอ้างอิงเพื่อหาส่วนที่ปรากฏซ้ำ (ใช้ \หมายเลข)

กลุ่มก้อนข้อความที่ล้อมด้วยวงเล็บสามารถนำมาใช้อ้างอิงซ้ำได้ โดยวงเล็บแรกจะเขียนแทนด้วย \1 และหากมีวงเล็บอื่นอีกก็เป็น \2 ตามลำดับ

ตัวอย่าง หาตัวเลขที่มีลักษณะเป็นตัวเลข ๓ ตัวโดยที่ตัวแรกกับตัวสุดท้ายเป็นตัวเดียวกัน
r = re.findall(r'(\d)\d\1','909 191 775 343')
print(r) # ได้ ['9', '1', '3']

แต่เมื่อใช้ () แล้วผลก็จะแสดงแค่เฉพาะตรงส่วนนั้น ดังนั้นถ้าต้องการทั้งหมดก็ต้องเอาวงเล็บครอบทั้งหมดอีกที แต่เมื่อมีวงเล็บด้านนอกซ้อนอยู่วงเล็บนั้นก็จะเป็นหมายเลข 1 แล้ววงเล็บด้านในก็จะถูกนับเป็นลำดับที่ 2 แทน จึงเขียนเป็น \2
r = re.findall(r'((\d)\d\2)','909 191 775 343')
print(r) # ได้ [('909', '9'), ('191', '1'), ('343', '3')]



การตั้งชื่อกลุ่มก้อน (ใช้ (?P<ชื่อ> ) และ (?P=ชื่อ))

ถ้าแค่ใช้วงเล็บสร้างกลุ่มก้อนไปธรรมดาการจะอ้างอิงถึงก็จะต้องใช้เป็นตัวเลข แต่บางครั้งก็ไม่สะดวกเพราะถ้ามีการเพิ่มกลุ่มก้อนใหม่ขึ้นมานำหน้าเลขก็จะเปลี่ยนไปทันที

เพื่อความสะดวกในบางครั้งอาจตั้งชื่อให้กลุ่มก้อนได้ ทำได้โดยเขียน (?P<ชื่อ> ) ชื่อนี้จะตั้งเป็นอะไรก็ได้ จากนั้นก็อ้างอิงถึงกลุ่มก้อนนั้นด้วย (?P=ชื่อ) หรือจะยังใช้ \หมายเลข เหมือนเดิมก็ยังได้อยู่

ตัวอย่าง
r = re.findall(r'((?P<ก้อน>\d)\d(?P=ก้อน))','909 191 775 343')
print(r) # ได้ [('909', '9'), ('191', '1'), ('343', '3')]
r = re.findall(r'((?P<ก้อน>\d)\d\2)','909 191 775 343')
print(r) # ได้ [('909', '9'), ('191', '1'), ('343', '3')]



การตั้งให้รูปแบบเปลี่ยนไปตามเงื่อนไข (ใช้ (?( ) | ) )

หากมีกลุ่มก้อนอักษรที่ใช้ ? หรือ * อยู่ อักษรกลุ่มนั้นอาจมีตัวตนอยู่หรือไม่ก็ได้ และในบางครั้งเราอาจต้องการให้รูปแบบที่จะตามมานั้นเปลี่ยนไปโดยขึ้นกับว่า กลุ่มนี้มีอยู่หรือเปล่า

สามารถทำได้โดยใส่ส่วนที่ต้องการให้เปลี่ยนตามเงื่อนไขในรูป (?(เลขหรือชื่อ)รูปแบบเมื่อมี|รูปแบบเมื่อไม่มี)

ที่อยู่ในวงเล็บด้านในก็คือตัวเลขที่แทนกลุ่มที่ต้องการให้เป็นตัวกำหนดเงื่อนไข หรือถ้าตั้งชื่อไว้ก็ใส่เป็นชื่อได้ แล้วหลังวงเล็บก็เป็นรูปแบบที่ต้องการให้ทำเมื่อมีตัวนั้นอยู่ จากนั้นคั่นด้วย | แล้วก็ตามด้วยรูปแบบเมื่อไม่มี

เพียงแต่ว่ากรณีที่ไม่ใส่รูปแบบเมื่อไม่มี จะละ | ไปเลยก็ได้ ใส่แค่รูปแบบเมื่อมีอย่างเดียวเฉยๆต่อจากวงเล็บ

เช่น ถ้าต้องการคำที่มีการขึ้นต้นด้วยตัวเลข แล้วก็ลงท้ายด้วยเลขนั้นซ้ำ หรือถ้าไม่ขึ้นต้นด้วยตัวเลขแต่แรกก็ต้องไม่มีตัวเลขต่อท้ายด้วย
r = re.findall(r'\b((\d)?[ก-ฮ]+(?(2)\2))\b','1กอ1 ข อย2 4ฮอ นป 2ส1')
print(r) # ได้ [('1กอ1', '1'), ('ข', ''), ('นป', '')]
print([x[0] for x in r]) # ได้ ['1กอ1', 'ข', 'นป']

ตัวอย่างอื่นๆอีก เช่น หากต้องการหาคำที่เป็นพยัญชนะตัวเดียวประกอบกับสระ "เ" หรือ "า" หรือ "ะ" ในจำนวนนี้มีสระ "เ" ที่ต้องวางอยู่ด้านหน้า ที่เหลืออยู่หลัง และบางครั้งก็อาจมีทั้งคู่ เช่น "เอะ"

หมายความว่าด้านหน้าพยัญชนะอาจมีสระ "เ" หรือไม่ก็ได้ และด้านหลังจะมี "า" หรือ "ะ" อยู่หรือไม่ก็ได้ ดังนั้นอาจเขียนได้เป็น
r = re.findall(r'\b(เ?[ก-ฮ]า?ะ?)\b','เล ละ เละ ลา เลา ล เลาะ')
print(r) # ได้ ['เล', 'ละ', 'เละ', 'ลา', 'เลา', 'ล', 'เลาะ']

แต่พอเขียนแบบนี้จะเห็นว่าแค่ "ล" ตัวเดียวซึ่งไม่มีทั้ง "เ" ตามหน้าและ "าะ" ตามหลังเลยก็เข้าข่ายด้วย

ถ้าหากเราไม่ต้องการก็ต้องตั้งเงื่อนไขว่าถ้าไม่มี "เ" นำหน้าจะต้องมี "า" หรือ "ะ" ตัวใดตัวหนึ่งตามหลัง แต่ถ้ามี "เ" นำหน้าแล้ว จะมี "า" และ "ะ" ตามหลังหรือไม่ก็ได้

ซึ่งจะเขียนได้ดังนี้
r = re.findall(r'\b((เ)?[ก-ฮ](?(2)า?ะ?|[าะ]))\b','เล ละ เละ ลา เลา ล เลาะ')
print(r) # ได้ [('เล', 'เ'), ('ละ', ''), ('เละ', 'เ'), ('ลา', ''), ('เลา', 'เ'), ('เลาะ', 'เ')]
print([x[0] for x in r]) # ได้ ['เล', 'ละ', 'เละ', 'ลา', 'เลา', 'เลาะ']



การกำหนดทางเลือกให้เข้าข่ายหลายตัว (ใช้ |)

บางครั้งเรามีรูปแบบที่ต้องการให้เข้าข่ายอยู่พร้อมกันหลายๆชุด ซึ่งอาจจะมีลักษณะบางอย่างร่วมกันบ้างหรือไม่มีเลย กรณีแบบนี้สามารถเขียนรูปแบบทั้งหมดที่ต้องการแล้วคั่นด้วย |

ตัวอย่าง เมื่อต้องการให้รูปแบบเป็น abc หรือ def
r = re.findall(r'abc|def','abc def ghi')
print(r) # ได้ ['abc', 'def']

หรือเช่นต้องการอักษร ๓ ตัวที่เป็นตัวเลขสลับกับตัวหนังสือ
r = re.findall(r'[a-z]\d[a-z]|\d[a-z]\d','1a1 2aa e3a 2b2 ddd e33 de2')
print(r) # ได้ ['1a1', 'e3a', '2b2']

ปกติถ้าไม่มีวงเล็บโค้ง () อยู่ | จะเป็นการแบ่งกั้นรูปแบบออกเป็น ๒ ส่วน แต่ผลของ | นั้นสามารถแบ่งคั่นได้ด้วยวงเล็บ () หากต้องการของเขตของการแบ่งแค่ตรงไหนก็ใช้ () ล้อมส่วนนั้น

ตัวอย่าง
r = re.findall(r'(?:il|la)_\S+','il_fiore la_foglia il_seme la_radice')
print(r) # ได้ ['il_fiore', 'la_foglia', 'il_seme', 'la_radice']



รายละเอียดอื่นๆ

นอกจากเนื้อหาทั้งหมดที่เขียนถึงไว้ในนี้แล้วก็ยังมีรายละเอียดปลีกย่อยอื่นๆอีก เช่นการปรับโหมดในการค้นต่างๆ เช่นว่าสามารถปรับให้พิจารณาอักษรพิมพ์ใหญ่พิมพ์เล็กเป็นตัวเดียวกัน สามารถเขียนโดยขึ้นบรรทัดใหม่ได้

อีกทั้งในนี้ได้แนะนำไปแค่ฟังก์ชันเดียวคือ re.findall เพื่อเป็นตัวอย่างทั้งหมด แต่จริงๆยังมีฟังก์ชันใน re ที่ใช้บ่อยอีกหลายตัวเช่น re.search, re.sub, re.split เป็นต้น

ส่วนที่ไม่ได้เขียนถึงตรงนี้จะยกไปเขียนถึงในโอกาสหน้า



อ้างอิง


-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python
-- คอมพิวเตอร์ >> เขียนโปรแกรม >> regex

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

目录

从日本来的名言
python
-- numpy
-- matplotlib

-- pandas
-- pytorch
maya
机器学习
-- โครงข่าย
     ประสาทเทียม
javascript
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  查看日志

  推荐日志

เรียนรู้วิธีการใช้ regular expression (regex)
หลักการเขียนทับศัพท์ภาษาจีนกวางตุ้ง
การใช้ unix shell เบื้องต้น ใน linux และ mac
หลักการเขียนทับศัพท์ภาษาจีนกลาง
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
บันทึกการเที่ยวสวีเดน 1-12 พ.ค. 2014
แนะนำองค์การวิจัยและพัฒนาการสำรวจอวกาศญี่ปุ่น (JAXA)
เล่าประสบการณ์ค่ายอบรมวิชาการทางดาราศาสตร์โดยโซวเคนได 10 - 16 พ.ย. 2013
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
บันทึกการเที่ยวญี่ปุ่นครั้งแรกในชีวิต - ทุกอย่างเริ่มต้นที่สนามบินนานาชาติคันไซ
หลักการเขียนทับศัพท์ภาษาญี่ปุ่น
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ
ทำไมถึงอยากมาเรียนต่อนอก
เหตุผลอะไรที่ต้องใช้ภาษาวิบัติ?