| |
การสร้างเว็บเพจโดยใช้ภาษา PHP บทที่
37
Regular Expression
Regular
Expression หรือเรียกย่อๆว่า Regex หมายถึง รูปแบบของลำดับ
หรือกลุ่มของสัญลักษณ์ ที่ใช้แทนลำดับ
หรือกลุ่มของอักขระตามที่ต้องการ
เราใช้สัญลักษณ์ [ ] (square brackets)
เพื่อกำหนดขอบเขตของกลุ่มตัวอักขระหลายตัวที่ใช้เป็นตัวเลือก
เช่น สมมุติว่า
เราต้องการจะเขียนรูปแบบที่ใช้แทนตัวอักขระหนึ่งตัว อะไรก็ได้จาก
{a,e,i,o,u} เราก็จะเขียนว่า [aeiou]
โดยจะเรียงลำดับก่อนหลังอย่างไรก็ได้ เช่น [eioua]
ให้ผลเหมือนกับ [aeoui] หรือ ถ้าเราต้องการเขียน
รูปแบบเพื่อใช้แทนตัวขระหนึ่งตัวที่เป็นตัวเลขตัวใดตัวหนึ่งจาก 0
ถึง 9 เราก็เขียนว่า [0123456789]
หรือจะเขียนแบบสั้นๆใหม่ได้เป็น [0-9] หรืออีกตัวอย่างหนึ่ง
ถ้าเราต้องการจะเขียนนิพจน์แบบ regex ขึ้นมา
เพื่อใช้แทนอักขระตัวใดตัวหนึ่งที่เป็นได้ทั้งตัวพิมพ์ใหญ่หรือเล็กในภาษาอังกฤษหรือตัวเลขระหว่าง
0 ถึง 9 เราก็เขียนว่า [A-Za-z0-9]
| [aeiou] |
ตัวอักขระตัวหนึ่งจาก {a,e,i,o,u}
ตัวไหนก็ได้ |
| [0-9] |
ตัวอักขระตัวหนึ่งจาก {0,1,...,9}
ตัวไหนก็ได้ |
| [A-Za-z0-9] |
ตัวอักขระตัวหนึ่งจาก {A,B,..,Z, a, b, ... , z, 0,
1, ... 9} ตัวไหนก็ได้ |
ถ้าเรามีข้อความแล้วเราต้องการจะค้นหาอักขระหรือลำดับของอักขระ
(หรือ pattern) ในข้อความเรานั้น
เราเรียกขั้นตอนในการค้นหาตามรูปแบบนี้ว่า pattern matching
ในภาษา PHP
จะมีฟังก์ชันที่เราใช้ในการค้นหาลำดับของตัวอักขระตามแบบที่ต้องการคือ
ereg() และ eregi() และต่างกันตรงที่ว่า ฟังก์ชัน eregi()
จะเปรียบเทียบโดยไม่คำนึงถึงเรื่องตัวพิมพ์เล็กหรือใหญ่
ตัวอย่างเช่น สมมุติว่า
เรามีข้อความอยู่ในอาร์เรย์เป็นข้อความที่มีแค่ตัวอักขระตัวเดียว
แล้วเราต้องการจะหาว่า ตัวไหนบ้างที่เป็นตัวเลข 0 ถึง 9
บ้างและตัวไหนบ้างที่เป็นตัวพิมพ์ภาษาอังกฤษ a, b, หรือ c
เราก็เขียนสคริปต์โดยใช้ฟังก์ชัน ereg() ได้ดังนี้
<?
$a=array("0","1","2","3","5","7","a","b","c");
for ($i=0; $i <
count($a); $i++) { // print only digit
if ( ereg("[0-9]",$a[$i]) ) {
print ("$a[$i]
<BR>\n"); }
} ?>
<HR> <?
for ($i=0; $i < count($a); $i++) { //
print only a, b or c if (
ereg("[a-c]",$a[$i]) ) {
print ("$a[$i]
<BR>\n"); }
}
?> |
ข้อความที่เราใช้ในตัวอย่างข้างบนมีแค่ตัวอักขระเพียงหนึ่งตัว
แต่อันที่จริงแล้วฟังก์ชัน ereg() จะให้ค่าเป็นจริง ถ้าพบว่า
ข้อความที่มีความยาวมากกว่าหนึ่งตัวอักขระและมีตัวอักขระอย่างน้อยหนึ่งตัวที่ตรงตามรูปแบบที่กำหนด
ฟังก์ชันก็จะให้ค่าเป็นจริงด้วย ตัวอย่างเช่น
<?
$a=array("f","mn",
"eU","+5","Y","17","a4","%m","cdef");
for($i=0; $i < count($a); $i++) {
if ( ereg("[a-z]",$a[$i]) ) {
print ("$a[$i]
<BR>\n"); }
}
?> |
ผลจากการทำงานของสคริปตในตัวอย่างนี้จะได้ว่า
ข้อความที่ตรงตามรูปแบบ [a-z] โดยใช้ฟังก์ชัน ereg()
ในการเปรียบเทียบ คือ "f", "mn", "eU", "a4", "%m" และ "cdef"
เพราะว่าข้อความเหล่านี้
มีตัวอักขระอย่างน้อยหนึ่งตัวที่อยู่ระหว่าง a ถึง z
ดังนั้นจึงจะเห็นได้ว่า ข้อความที่เหลือคือ "+5", "Y" และ "17"
ไม่ตรงตามรูปแบบ
จากตัวอย่างข้างบน สมมุติว่า
เราต้องการจะหาข้อความที่มีสองตัวอักขระและมีแค่สองตัวเท่านั้น
เป็นตัวใดก็ได้ระหว่าง a ถึง z
เราก็จะต้องกำหนดรูปแบบให้การค้นหาให้เป็น ^[a-z]{2}$
โดยที่สัญลักษณ์ ^ หมายถึงการเริ่มต้น และ $ หมายถึงการลงท้าย
และเราจะอ่านว่า
ให้ค้นหาข้อความที่เริ่มต้นด้วยตัวภาษาอังกฤษพิมพ์เล็ก
และจบด้วยตัวภาษาอังกฤษพิมพ์เล็ก และมีอยู่สองตัวเท่านั้น
จากตัวอย่างข้างบน ถ้าเราใช้รูปแบบใหม่นี้ในการค้นหา เราจะได้
"en" เป็นข้อความเดียวเท่านั้นที่ตรงตามรูปแบบ
สมมุติว่า
เราต้องการค้นหาคำที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่ภาษาอังกฤษและตามด้วยสระ
{a,e,i,o,u}
ถ้าข้อความมีมากกว่าสองตัวอักขระแล้วตัวที่ตามมาจะเป็นอะไรก็ได้
เราก็เขียนรูปแบบในการค้นหาได้ เป็น ^[A-Z][aeiou]
ลองตัวดูอย่างต่อไปนี้
<?
$a=array("f","Monday",
"eU","755","Pu","English","Tuesday","for", "Bee");
for($i=0; $i <
count($a); $i++) { if (
ereg("^[A-Z][aeiou]",$a[$i]) ) {
print ("$a[$i]
<BR>\n"); }
}
?> |
ตัวอย่างนี้จะได้ว่า "Monday", "Pu" ,"Tuesday" และ "Bee"
คือข้อความที่ตรงตามรูปแบบที่กำหนด
ถ้าต้องการจะหาข้อความที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่แล้วตามด้วยสระเป็นตัวพิมพ์เล็กอย่างน้อยหนึ่งตัว
เราก็เขียนว่า ^[A-Z][aeiou]+$
ซึ่งเครื่องหมายบวกที่อยู่ข้างหลัง [aeiou] หมายความว่า
มีได้อย่างน้อยที่สุดหนึ่งตัว จากตัวอย่างข้างบน
ถ้าเราใช้รูปแบบใหม่นี้ในการค้นหา ก็จะได้ข้อความ "Pu" และ "Bee"
เท่านั้นที่ตรงตามรูปแบบ
ถ้าจะหาข้อความที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่แต่ตามด้วยตัวพิมพ์เล็กใดๆก็ได้ที่ไม่ใช่สระ
{a,e,i,o,u} เราก็เขียนใหม่ได้เป็น ^[A-Z][^aeiou] โปรดสังเกตว่า
เราใส่สัญลักษณ์ ^ ไว้ระหว่าง [ ] และอยู่ข้างหน้าสุด
เพื่อใช้กำหนดกรณีตรงข้าม และจากตัวอย่างข้างบน เราจะได้ข้อความ
"English" เท่านั้นที่ตรงตามรูปแบบใหม่นี้
อีกตัวอย่างหนึ่งที่น่าสนใจ คือ สมมุติว่า
เรามีรายชื่อไฟล์อยู่หลายๆชื่อ ต้องการจะตรวจดูว่า
ชื่อไหนลงท้ายด้วย .gif .jpeg .jpg หรือ .png บ้าง โดยใช้
eregi() ในการค้นหา เราจะต้องกำหนดรูปแบบของ regex ขึ้นมาก่อน
ซึ่งทำได้ดังนี้ (\.gif|\.jpg|\.jpeg|\.png)$
ในกรณีนี้เราไม่ได้ใช้ [ ] แต่ใช้วงเล็บคู่ ( ) แทน และสัญลักษณ์
\. เป็น escape sequence ที่เราใช้แทนจุด (.)
ถ้าเขียนอยู่ในระหว่างวงเล็บคู่ เนื่องจากว่าถ้าใช้จุดโดยไม่มี
backslash (\) นำหน้าก็จะหมายถึง ตัวอักขระใดๆก็ได้
ถ้าเราใช้จุดระหว่าง [ ] ก็จะหมายถึงจุด โดยไม่ต้องใส่ \
ไว้เพื่อกำหนดให้เป็น escape sequence
<?
$files=array("bird.gif","Linux.JPG",
"unknown.xbm","icon.Png");
for($i=0; $i < count($files); $i++)
{ if (
eregi("(\.gif|\.jpg|\.jpeg|\.png)$",$files[$i]) ) {
print ("$files[$i]
<BR>\n"); }
}
?> |
ความแตกต่างของการใช้ ( ) และ [ ] อยู่ที่ว่า ถ้าเขียน
(abc) หมายถึงข้อความที่เริ่มด้วย a ตามด้วย b และ c ตามลำดับ
ในขณะที่ [abc] หมายถึง a หรือ b หรือ c ซึ่ง [abc]
จะให้ผลเหมือนกับ (a|b|c) และเครื่องหมาย | ที่ใช้ภายในวงเล็บคู่
( ) จะหมายถึง "หรือ" ดังนั้นจากตัวอย่างข้างบน จากรูปแบบเดิม
(\.gif|\.jpg|\.jpeg|\.png)$ เราอาจจะเขียนใหม่ได้เป็น
[(\.gif|\.png)(\.jpg|\.jpeg)]$ ก็จะให้ผลเหมือนกัน
จากที่ได้อธิบายมาก็เป็นเพียงการใช้งานส่วนหนึ่งของ
Regular Expression
ซึ่งยังมีลักษณะและการใช้งานที่นอกเหนือจากที่กล่าวไป
สัญลักษณ์พื้นฐานที่ใช้ในการเขียน Regular
Expression
| . |
ตัวอักขระใดๆก็ได้ |
| [ ... ] |
ตัวอักขระตัวใดๆก็ได้ที่อยู่ในกลุ่มของตัวอักขระที่เป็นตัวเลือก |
| [^... ] |
ตัวอักขระตัวใดๆก็ได้ที่ไม่ได้อยู่ในกลุ่มของตัวอักขระที่เป็นตัวเลือก |
| ^ |
ตำแหน่งเริ่มต้นของข้อความ |
| $ |
ตำแหน่งท้ายสุดของข้อความ |
| \< |
ตำแหน่งเริ่มต้นของคำ |
| \> |
ตำแหน่งท้ายสุดของคำ |
| | |
สัญลักษณ์ที่ใช้แยกตัวเลือกระหว่าง ( ...
) |
| (...) |
ใช้แทนกลุ่มของตัวเลือก |
Repetition Quantifiers
| ? |
ถ้ามีก็ไม่เกินหนึ่งตัวหรือไม่มีก็ได้ |
| * |
มีหนึ่งตัวหรือมากกว่าหนึ่งหรือไม่มีเลยก็ได้ |
| + |
มีหนึ่งตัวหรือมากกว่าหนึ่งก็ได้
แต่ต้องมีอย่างน้อยหนึ่งตัว |
| {min,max} |
ใช้กำหนดจำนวนน้อยที่สุดและมากที่สุดที่จะมีได้ |
ตัวอย่างของการใช้ regular expressions
| ^be |
ข้อความที่ขึ้นต้นด้วย b และถัดจาก b ตามด้วย
e |
| ^[be] |
ข้อความที่ขึ้นต้นด้วย b หรือ e |
| [^be] |
ข้อความที่ไม่ได้ขึ้นต้นด้วย b และ
e |
| ion$ |
ข้อความที่ลงท้ายด้วยหรือจบท้ายด้วย
ion |
| [ion]$ |
ข้อความที่ลงท้ายหรือจบท้ายด้วย i หรือ o
หรือ n |
| \n$ |
ข้อความที่มีสัญลักษณ์ \n (new line)
อยู่ท้าย |
| <H[1-6]> |
ข้อความที่มี <H1> <H2>
<H3> <H4> <H5> หรือ <H6>
อยู่ด้วย |
| <H[^4-6]> |
ข้อความที่ไม่มี <H4> <H5> และ
<H6> อยู่ด้วย |
| [0-9.] |
ข้อความที่มีตัวเลขใดๆระหว่าง 0 ถึง 9 หรือ
จุด อยู่ด้วย |
| ^Subject$ |
ข้อความที่มีคำว่า Subject
เท่านั้น |
| ^(From|Subject|Date): |
ข้อความที่มีคำว่า From: หรือ Subject: หรือ Date:
ขึ้นต้น |
| ^[0-9]+$ |
ข้อความที่มีตัวเลขเท่านั้นและอย่างน้อยหนึ่งตัว |
| ([0-9]+(\.[0-9]+){3}) |
ข้อความที่ตรงตามรูปแบบของหมายเลข IP เช่น
127.0.0.1 |
| ^[-+]?[0-9]+(\.[0-9]*)?$ |
ข้อความที่ตรงตามรูปแบบของตัวเลขทศนิยม เช่น
-12.345 |
การใช้งาน
regular expression อย่างจริงจังนั้นไม่ใช่เป็นเรื่องง่าย
ต้องทำความเข้าใจอย่างจริงจัง
และในเอกสารนี้ก็ทำได้แค่นำเสนอเนื้อหาพื้นฐานสำหรับการใช้งานเท่านั้น
ถ้าใครสนใจการใช้งานอย่างจริงจัง ในเรื่องของ regular expression
ก็สามารถหาหนังสือ สำหรับเรื่องนี้โดยเฉพาะมาอ่านได้ by iqjung
|