Regular Expression คืออะไรน่ะ (ภาษาไทยแปลว่า “นิพจน์ปรกติ”)
มันเป็นหนึ่งในวิธีการ ค้นหา/คัดกรอง ข้อความที่มีลักษณะและรูปแบบตรงกับที่เราต้องการ หรือถ้าจะเอาแบบภาษาบ้านๆก็จะประมาณที่เราบอกคอมพิวเตอร์ว่า
“เห้ย…ึงช่วยหาข้อความคล้ายๆแบบนี้ออกมาให้หน่อยดิ.”
แต่…เดี๋ยวนะมันเขียนโปรแกรมแบบนั้นด้วยหรอ
จริงๆหลายคนอาจจะเคยผ่านตากันมาแล้วแต่ไม่ทันรู้สึกตัว
SQL
SELECT name FROM Customers WHERE Country=’Mexico’;
แปลเป็นภาษาไทยแบบชาวบ้านจะได้ความว่า
คัดแยกเอา รายชื่อ ของ ลูกค้า ทั้งหมดจากประเทศ Mexico มาซิ
โอเค ออกทะเลไปไกลละกลับเข้าเรื่องดีกว่า..ส่วนใครไม่อยากกลับเข้าฝั่งไปหาอ่านต่อเองในเรื่อง Declarative programming นะ
Regular Expression (เรกูลาร์ เอ็กซ์เพรชชัน) หรือเรียกย่อๆว่า Regex (เร็ก-เอ็กซ์ ) ไม่มีใครอ่านผิดเป็น เร็กเก้ ใช่ไหม
มีคนกล่าวไว้ว่าตอนแรกเป็นจุดเด่นอย่างนึงของภาษา perl แล้วค่อยแพร่ไปภาษาอื่นๆทีหลัง ตอนนี้ภาษาหลักก็มีกันเกือบหมดแล้ว C/C++ Java Python Ruby PHP JavaScript .NET แต่จะมีรูปแบบแต่ต่างกันไปเล็กน้อย
เรามาดูตัวอย่างดีกว่า
สมมุติมี ข้อความตามนี้ แล้วเรา
ต้องการทราบ ค่าน้ำหนักที่เป็น
ตัวเลขในแต่ละบรรทัดจะทำยังไง?
ทางซ้ายนั้นไม่ใช้regexทำโดยวิธีวนลูปไปทีละ2ตัวอักษรแล้วเช็คว่าเป็นตัวเลขหรือเปล่า ส่วนทางขวาใช้regex ทั้ง2แบบให้ผลลัพท์เหมือนกัน
ว่าแต่codeทางฝั่งขวามันทำงานยังไงน่ะ
import re #import module
fileT = open('data.txt', 'r')
text = fileT.read()pattern='\d\d' #กำหนดpatternของตัวอักษร
regex = re.compile(pattern) #create regex object
weights = regex.findall(text) #ค้นหาผลลัพท์
findall()
เป็นคำสั่งที่เริ่มค้นหาจริงๆ โดยreturn กลับมาเป็น List ของผลลัพท์ทุกตัว
ส่วนรายละเอียดของpattern มีคร่าวๆดังนี้
แบบที่นิยมใช้กัน
\d เอาตัวเลข 0–9 ให้ผลลัพท์ เทียบเท่า [0–9]
\D ตัวอื่นนอกจากตัวเลข 0–9 ให้ผลลัพท์ เทียบเท่า[^ 0-9]
\t แท็บ
\n ขึ้นบรรทัดใหม่
\s สเปซบาร์หรือแท็บหรือขึ้นบรรทัดใหม่ [\n\t\r\f\v]
\S ตัวอื่นนอกจากสเปซบาร์หรือแท็บหรือขึ้นบรรทัดใหม่ [^s]
\w ตัวเลขและอักษรภาษาอังกฤษรวมถึงขีดล่างเทียบเท่า [A-Za-z0–9_]
\W ตัวอื่นที่ไม่ใช่ \w เทียบเท่า[^w]
. (จุด)แทนตัวอักษรอะไรก็ได้
bracket expression แบบกำหนดคร่าวๆ
[abc] ต้องเป็นตัว a หรือ b หรือ c
[a-z] ได้ทุกตัวตั้งแต่a-z
[abcx-z] ได้ตัว a,b,c,x,y,zเท่านั้น
[A-Za-z] ได้ตัว a-z และA-Z
[0–9] ตัวเลข 0 ถึง 9 ให้ผลเหมือนกับ \d
[ก-๙] ได้ภาษาไทย พยัญชนะ สระ และตัวเลขไทย ทั้งหมดเลย
จริงๆมีวิธีและเทคนิคการเขียนตัวpattern อีกเยอะเลย ผมจะแปะlinkไว้ด้านล่างนะครับ ส่วนblogนี้เราจะมาดูว่า มีฟังก์ชั่นอะไร ใช้งานอย่างไรบ้าง
ตัวอย่างที่2
ลองสังเกตุดู \d นั้นหมายถึงเอาตัวเลข แต่ทำไมoutput ถึงมีแต่พ.ศ. ไม่มีวันที่ละ
แล้วทำไม ต้อง\d ถึง4ครั้งด้วย…..
r'\d\d\d\d' ความหมายของมันคือ เอาตัวเลข[0-9]ที่เรียงติดกัน4ตัว ส่วนตัวrหมายถึงraw string ตัวอักษรจะไม่มีการเปลี่ยนเป็นอักขระพิเศษเพราะฉะนั้นผู้ที่ผ่านเข้ารอบจึงมีแค่ปีพ.ศ.เท่านั้น
แล้วถ้าเกิดเปลี่ยนtextเป็นแบบนี้ 256100 และ 002550 ละ (ตัวเลขเกิน4หลัก)
text = 'สมชาย เกิดวันที่ 17 สิงหาคม ปี พ.ศ. 256100. สมหญิงเกิดวันที่ 22 กุมภาพันธ์ 002550'
#ผลลัพท์จะเป็น['2561', '0025']
finditer() เก็บข้อมูลระหว่างการค้นหาไว้ให้ด้วย
sub() คือการเขียนทับข้อความตรงส่วนนั้นๆ เช่น
text = 'สมชาย เกิดวันที่ 17 สิงหาคม ปี พ.ศ. 2561. สมหญิงเกิดวันที่ 22 กุมภาพันธ์ 2550'
mtext = re.sub('\d\d\d\d',r'****',text)
print(mtext)
# output สมชาย เกิดวันที่ 17 สิงหาคม ปี พ.ศ. ****. สมหญิงเกิดวันที่ 22 กุมภาพันธ์ ****
Split() ลบข้อมูลตรงส่วนนั้นออก และตัดข้อความออกจากกัน
text = 'สมชาย เกิดวันที่ 17 สิงหาคม ปี พ.ศ. 2561 สมหญิงเกิดวันที่ 22 กุมภาพันธ์ 2550'
mtext = re.split('\s\d\d\d\d',text)
print(mtext)
# output ['สมชาย เกิดวันที่ 17 สิงหาคม ปี พ.ศ.', ' สมหญิงเกิดวันที่ 22 กุมภาพันธ์', '']
ก็ขอจบblogแต่เพียงเท่านี้ละครับ blogหน้าจะเป็นเกี่ยวกับpatternล้วนๆแล้ว (ปล.ถ้าได้เขียนนะ)
ตารางpatternดูอันข้างล่างนี้เข้าใจได้ง่าย
อธิบาย pattern แบบละเอียดพร้อมคำอธิบายประกอบ