φυβλαςのβλογ
บล็อกของ phyblas



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

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

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

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

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

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

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

ในภาษาไพธอนมีมอดูล (ไลบรารี) ที่ใช้สำหรับจัดการกับ 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

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

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
python
-- numpy
-- matplotlib

-- pandas
-- pytorch
maya
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
เรียนภาษาจีน
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



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

  ค้นหาบทความ

  บทความแนะนำ

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

บทความแต่ละเดือน

2019年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2018年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2017年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2016年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2015年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

ค้นบทความเก่ากว่านั้น

ไทย

日本語

中文