Regular Expressions

การใช้งาน string ที่มีประสิทธิภาพของ Ruby ยังไม่จบเพียงเท่านั้น Ruby ยังมีความสามารถในการทำงานของ pattern ด้วยการใช้ความหมายพิเศษ โดยมี:


[] range specificication (e.g., [a-z] means a letter in the range a to z)
\w letter or digit; same as [0-9A-Za-z]
\W neither letter or digit
\s space character; same as [ \t\n\r\f]
\S non-space character
\d digit character; same as [0-9]
\D non-digit character
\b backspace (0x08) (only if in a range specification)
\b word boundary (if not in a range specification)
\B non-word boundary
* zero or more repetitions of the preceding
+ one or more repetitions of the preceding
{m,n} at least m and at most n repetitions of the preceding
? at most one repetition of the preceding; same as {0,1}
| either preceding or next expression may match
() grouping

เราจะเรียก pattern ที่มีความหมายพิเศษเหล่านี้ว่า regular expressions ใน Ruby ก็ไม่ต่างจาก Perl เราจะนิยมใช้ forward slash (/) มากกว่า double-quoted ("...") ถ้าคุณไม่เคยใช้ regular expressions มาก่อนเลยซึ่้งที่จริงแล้วมันง่ายมากๆ เราหวังว่าคุณจยอมเสียเวลาที่จะเรียนรู้กับมันสักนิดเพื่อให้คุ้นเคยมากขึ้น Regular expressions มีความสามารถมากซึ่งจะทำให้คุณเขียน Ruby ได้ง่ายขึ้นและสั้นไปอีกหลายบรรทัดเมือคุณต้องการที่จะ จับคู่,ค้นหาหรือแม้กระทั่งจัดการกับข้อความ strings

ตัวอย่าง, สมมุติว่าเราต้องการจะทดสอบ string ว่าตรงตามความต้องการว่า: "เริ่มด้วย f ตัวเล็กและตามด้วยอักษรตัวใหญ่หนึ่งตัวและอาจจะมีข้อมูลอย่างอื่นอีกจนกว่าจ ะไม่มีตัวอักษรตัวเล็ก" ถ้าเคยเขียนภาษา C จะรู้ว่าอาจจะเขียนเป็นหลายสิบบรรทัดเลย แต่ถ้าเป็น Ruby ก็แต่เรียกใช้ regular expression ดังนี้ /^f[A-Z](^[a-z]*$/.

ลองดูตัวอย่าง โดยมีความต้องการว่า: "มีเลขฐาน 16 ภายใต้ วงเล็บสามเหลี่ยม" ง่ายมาก

ruby> def chab(s)   # "contains hex in angle brackets"
    |    (s =~ /<0(x|X)(\d|[a-f]|[A-F])+>/) != nil

    | end
  nil
ruby> chab "Not this one."
  false
ruby> chab "Maybe this? {0x35}"    # wrong kind of brackets
  false
ruby> chab "Or this? <0x38z7e>"    # bogus hex digit

  false
ruby> chab "Okay, this: <0xfc0004>."
  true

ความจริงแล้ว regular expressions จะทำให้งงเล็กน้อยในตอนแรก แต่คุณจะชอบมันอย่างรวดเร็ว

จากนี้เป็นตัวอย่างให้เราทำความเข้าใจให้มากขึ้นกับ regular expressions โดยทำการเก็บเป็นไฟล์ชื่อ regx.rb แล้ว run ด้วยคำสั่ง "ruby regx.rb"

# Requires an ANSI terminal!

st = "\033[7m"
en = "\033[m"

while TRUE
  print "str> "
  STDOUT.flush
  str = gets
  break if not str
  str.chop!
  print "pat> "
  STDOUT.flush
  re = gets
  break if not re
  re.chop!
  str.gsub! re, "#{st}\\&#{en}"
  print str, "\n"
end
print "\n"

program จะทำการเรียกให้ใส่ input 2 ครั้ง โดยครั้งแรกจะเป็น ข้อความและัส่วนที่สองเป็น regular expressions โดยที่ ข้อความจะถูกทดสอบกับ regular expression และทำการแสดงผลส่วนที่ตรงตาม regular expression

str> foobar

pat> ^fo+

foobar

~~~

เราจะเห็นตัวหนังสือสีแดงและ "~~~" ในกรณีที่เป็น rex-based browser

ลองหลายๆ input

str> abc012dbcd555

pat> \d

abc012dbcd555

~~~ ~~~

ถ้าไม่เข้าใจในการใช้ regular expressions ให้กลับไปลองดูที่ตาราง: \d หมายถึงไม่มีความสัมพันธ์กับตัวอักษรแต่จะจับกับตัวเลข

แล้วจะเป็นอย่างไรเมื่อสามารถจับคู่ได้มากกว่า 1 คู่?

str> foozboozer

pat> f.*z

foozboozer

~~~~~~~~

foozbooz เป็นผลลัพธ์แทนที่จะเป็น fooz เพราะฉะนั้น regular expressions จะจับกับอันที่ยาวที่สุด

ตัวอย่างนี้เป็นการจับกัยส่วนที่มี colon-delimited ของเวลา

str> Wed Feb  7 08:58:04 JST 1996

pat> [0-9]+:[0-9]+(:[0-9]+)?

Wed Feb 7 08:58:04 JST 1996

~~~~~~~~

"=~" เป็นเครื่องหมายที่อยู่ในการทำงานของ regular expressions ด้วยเช่นกัน มันจะทำการ return ค่าตำแหน่งใน string ที่สามารถจับคู่ได้และ nil ถ้า pattern นั้นไม่สามารถจับคู่ได้

ruby> "abcdef" =~ /d/

3

ruby> "aaaaaa" =~ /d/

nil

Tue, 25 Jul 2006 16:03 Posted in

Tags , , , ,

Comment Regular Expressions


RSS