1. 程式人生 > >Ruby學習之正則表示式的使用

Ruby學習之正則表示式的使用

正則表示式是一種特殊序列的字元,它通過使用有專門語法的模式來匹配或查詢字串集合,並且用事先定義好的一些特定字元、及這些特定字元的組合,組成一個"規則字串",這個"規則字串"用來表達對字串的一種過濾邏輯,它從字面上看是一種介於斜槓之間或介於跟在 %r 後的任意分隔符之間的模式,來看下它的語法:

/pattern/
/pattern/im    # 可以指定選項
%r!/usr/local! # 使用分隔符的正則表示式

例項如下:

#!/usr/bin/ruby
 
line1 = "Cats are smarter than dogs";
line2 = "Dogs also like meat";
 
if ( line1 =~ /Cats(.*)/ )
  puts "Line1 contains Cats"
end
if ( line2 =~ /Cats(.*)/ )
  puts "Line2 contains  Dogs"
end

正則表示式從字面上看可能包含一個可選的修飾符,用於控制各方面的匹配,修飾符在第二個斜槓字元後指定,我們來看下其中的一些修飾符:

修飾符 描述
i 當匹配文字時忽略大小寫。
o 只執行一次 #{} 插值,正則表示式在第一次時就進行判斷。
x 忽略空格,允許在整個表示式中放入空白符和註釋。
m 匹配多行,把換行字元識別為正常字元。
u,e,s,n 把正則表示式解釋為 Unicode(UTF-8)、EUC、SJIS 或 ASCII。如果沒有指定修飾符,則認為正則表示式使用的是源編碼。

就像字串通過 %Q 進行分隔一樣,Ruby 允許我們以 %r 作為正則表示式的開頭,後面跟著任意分隔符。這在描述包含大量我們不想轉義的斜槓字元時非常有用,來看下例項:

# 下面匹配單個斜槓字元,不轉義
%r|/|               
 
# Flag 字元可通過下面的語法進行匹配
%r[</(.*)>]i

除了控制字元,(+ ? . * ^ $ ( ) [ ] { } | \),其他所有字元都匹配本身,我們可以通過在控制字元前放置一個反斜槓來對控制字元進行轉義,下面來看下 Ruby 中可用的正則表示式語法:

模式 描述
^ 匹配行的開頭。
$ 匹配行的結尾。
. 匹配除了換行符以外的任意單字元。使用 m 選項時,它也可以匹配換行符。
[...] 匹配在方括號中的任意單字元。
[^...] 匹配不在方括號中的任意單字元。
re* 匹配前面的子表示式零次或多次。
re+ 匹配前面的子表示式一次或多次。
re? 匹配前面的子表示式零次或一次。
re{ n} 匹配前面的子表示式 n 次。
re{ n,} 匹配前面的子表示式 n 次或 n 次以上。
re{ n, m} 匹配前面的子表示式至少 n 次至多 m 次。
a| b 匹配 a 或 b。
(re) 對正則表示式進行分組,並記住匹配文字。
(?imx) 暫時開啟正則表示式內的 i、 m 或 x 選項。如果在圓括號中,則隻影響圓括號內的部分。
(?-imx) 暫時關閉正則表示式內的 i、 m 或 x 選項。如果在圓括號中,則隻影響圓括號內的部分。
(?: re) 對正則表示式進行分組,但不記住匹配文字。
(?imx: re) 暫時開啟圓括號內的 i、 m 或 x 選項。
(?-imx: re) 暫時關閉圓括號內的 i、 m 或 x 選項。
(?#...) 註釋。
(?= re) 使用模式指定位置。沒有範圍。
(?! re) 使用模式的否定指定位置。沒有範圍。
(?> re) 匹配無回溯的獨立模式。
\w 匹配單詞字元。
\W 匹配非單詞字元。
\s 匹配空白字元。等價於 [\t\n\r\f]。
\S 匹配非空白字元。
\d 匹配數字。等價於 [0-9]。
\D 匹配非數字。
\A 匹配字串的開頭。
\Z 匹配字串的結尾。如果存在換行符,則只匹配到換行符之前。
\z 匹配字串的結尾。
\G 匹配最後一個匹配完成的點。
\b 當在括號外時匹配單詞邊界,當在括號內時匹配退格鍵(0x08)。
\B 匹配非單詞邊界。
\n, \t, etc. 匹配換行符、回車符、製表符,等等。
\1...\9 匹配第 n 個分組子表示式。
\10 如果已匹配過,則匹配第 n 個分組子表示式。否則指向字元編碼的八進位制表示。

來看下正則匹配字元的例項:

例項 描述
/ruby/ 匹配 "ruby"
¥ 匹配 Yen 符號。Ruby 1.9 和 Ruby 1.8 支援多個字元。

匹配字元類例項:

例項 描述
/[Rr]uby/ 匹配 "Ruby" 或 "ruby"
/rub[ye]/ 匹配 "ruby" 或 "rube"
/[aeiou]/ 匹配任何一個小寫母音字母
/[0-9]/ 匹配任何一個數字,與 /[0123456789]/ 相同
/[a-z]/ 匹配任何一個小寫 ASCII 字母
/[A-Z]/ 匹配任何一個大寫 ASCII 字母
/[a-zA-Z0-9]/ 匹配任何一個括號內的字元
/[^aeiou]/ 匹配任何一個非小寫母音字母的字元
/[^0-9]/ 匹配任何一個非數字字元

還有就是匹配特殊字元類:

例項 描述
/./ 匹配除了換行符以外的其他任意字元
/./m 在多行模式下,也能匹配換行符
/\d/ 匹配一個數字,等同於 /[0-9]/
/\D/ 匹配一個非數字,等同於 /[^0-9]/
/\s/ 匹配一個空白字元,等同於 /[ \t\r\n\f]/
/\S/ 匹配一個非空白字元,等同於 /[^ \t\r\n\f]/
/\w/ 匹配一個單詞字元,等同於 /[A-Za-z0-9_]/
/\W/ 匹配一個非單詞字元,等同於 /[^A-Za-z0-9_]/

再來就是匹配重複字元:

例項 描述
/ruby?/ 匹配 "rub" 或 "ruby"。其中,y 是可有可無的。
/ruby*/ 匹配 "rub" 加上 0 個或多個的 y。
/ruby+/ 匹配 "rub" 加上 1 個或多個的 y。
/\d{3}/ 剛好匹配 3 個數字。
/\d{3,}/ 匹配 3 個或多個數字。
/\d{3,5}/ 匹配 3 個、4 個或 5 個數字。

還有非貪婪模式匹配重複,也就是匹配最小次數的重複:

例項 描述
/<.*>/ 貪婪重複:匹配 "<ruby>perl>"
/<.*?>/ 非貪婪重複:匹配 "<ruby>perl>" 中的 "<ruby>"

可以通過圓括號進行分組:

例項 描述
/\D\d+/ 無分組: + 重複 \d
/(\D\d)+/ 分組: + 重複 \D\d 對
/([Rr]uby(, )?)+/ 匹配 "Ruby"、"Ruby, ruby, ruby",等等

還有就是反向引用,也就是再次匹配之前匹配過的分組:

例項 描述
/([Rr])uby&\1ails/ 匹配 ruby&rails 或 Ruby&Rails
/(['"])(?:(?!\1).)*\1/ 單引號或雙引號字串。\1 匹配第一個分組所匹配的字元,\2 匹配第二個分組所匹配的字元,依此類推。

匹配替換的例項如下:

例項 描述
/ruby|rube/ 匹配 "ruby" 或 "rube"
/rub(y|le))/ 匹配 "ruby" 或 "ruble"
/ruby(!+|\?)/ "ruby" 後跟一個或多個 ! 或者跟一個 ?

再來就是錨匹配了,在這裡呢,需要指定匹配位置:

例項 描述
/^Ruby/ 匹配以 "Ruby" 開頭的字串或行
/Ruby$/ 匹配以 "Ruby" 結尾的字串或行
/\ARuby/ 匹配以 "Ruby" 開頭的字串
/Ruby\Z/ 匹配以 "Ruby" 結尾的字串
/\bRuby\b/ 匹配單詞邊界的 "Ruby"
/\brub\B/ \B 是非單詞邊界:匹配 "rube" 和 "ruby" 中的 "rub",但不匹配單獨的 "rub"
/Ruby(?=!)/ 如果 "Ruby" 後跟著一個感嘆號,則匹配 "Ruby"
/Ruby(?!!)/ 如果 "Ruby" 後沒有跟著一個感嘆號,則匹配 "Ruby"

再來就是小括號裡的特殊語法了:

例項 描述
/R(?#comment)/ 匹配 "R"。所有剩餘的字元都是註釋。
/R(?i)uby/ 當匹配 "uby" 時不區分大小寫。
/R(?i:uby)/ 與上面相同。
/rub(?:y|le))/ 只分組,不進行 \1 反向引用

subgsub 及它們的替代變數 sub!gsub! 是使用正則表示式時重要的字串方法。所有這些方法都是使用正則表示式模式執行搜尋與替換操作。subsub! 替換模式的第一次出現,gsubgsub! 替換模式的所有出現。subgsub 返回一個新的字串,保持原始的字串不被修改,而 sub!gsub! 則會修改它們呼叫的字串,來看例項:

#!/usr/bin/ruby
# -*- coding: UTF-8 -*-
 
phone = "138-3453-1111 #這是一個電話號碼"
 
# 刪除 Ruby 的註釋
phone = phone.sub!(/#.*$/, "")   
puts "電話號碼 : #{phone}"
 
# 移除數字以外的其他字元
phone = phone.gsub!(/\D/, "")    
puts "電話號碼 : #{phone}"

 最後再來看一個例項:

#!/usr/bin/ruby
# -*- coding: UTF-8 -*-
 
text = "rails 是 rails,  Ruby on Rails 非常好的 Ruby 框架"
 
# 把所有的 "rails" 改為 "Rails"
text.gsub!("rails", "Rails")
 
# 把所有的單詞 "Rails" 都改成首字母大寫
text.gsub!(/\brails\b/, "Rails")
 
puts "#{text}"

好啦,本次記錄就到這裡了。

如果感覺不錯的話,請多多點贊支援哦。。。