การสร้างเว็บเพจโดยใช้ภาษา
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
ก็สามารถหาหนังสือ สำหรับเรื่องนี้โดยเฉพาะมาอ่านได้
|