[python] ลองเล่น Regular Expression ตอนที่ 1

minatorak
3 min readDec 28, 2017

--

28/12/2017

บทความชุดนี่ มีทั้งหมด 3 ตอนนะครับ

[python] Regular Expressions ตอนที่ 2

[Python] Regular Expressions ตอนที่ 3 by Examples

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 กุมภาพันธ์ ****
count ถ้าใส่ 1 จะทำกับแค่พ.ศ.ของสมชาย สมหญิงเป็นเลขปกติ

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 แบบละเอียดพร้อมคำอธิบายประกอบ

--

--