Ruby對正則表達式支持非常好,下面將對我經常使用到的做一個總結,包括Ruby中正則的寫法,匹配的方法,替換,分組匹配等。
1、Ruby中正則表達式的寫法
主要有三種
- 在//之間,要進行轉義
- 在%r{}內,不用進行轉義
- Regexp.new()內,不用進行轉義
/mm\/dd/,Regexp.new(“mm/dd”),%r{mm/dd}三者效果相同,實質都是新建了一個Regexp的類。
2、匹配的兩種方法
- =~肯定匹配, !~否定匹配。=~表達式返回匹配到的位置索引,失敗返回nil,符號左右內容可交換
- regexp#match(str),返回MatchData,一個數組,從0開始,還有match.pre_match返回匹配前內容,match.post_match返回匹配後內容
/cat/ =~ "dog and cat" #返回8
mt = /cat/.match("bigcatcomes")
"#{mt.pre_match}->#{mt[0]}<-#{mt.post_match}" #返回big->cat<-comes
3、替換
很多時候匹配是爲了替換,Ruby中進行正則替換非常簡單,兩個方法即可搞定,sub()+gsub()。
sub只替換第一次匹配,gsub(g:global)會替換所有的匹配,沒有匹配到返回原字符串的copy
str = "ABDADA"
new_str = str.sub(/A/, "*") #返回"*BDADA"
new_str2 = str.gsub(/A/, "*") #返回"*BD*D*"
如果想修改原始字符串用sub!()和gsub!(),沒有匹配到返回nil。
方法後面還可以跟block,對匹配的字符串進行操作
a.gsub(/[aeiou]/) {|vowel| vowel.upcase } # => "qUIck brOwn fOx"
4、分組匹配
Ruby的分組匹配與其它語言差別不大,分組匹配表達式是對要進行分組的內容加()。
對於匹配到的結果,可以用系統變量#$1,#$2…索引,也可用matchData數組來索引
md = /(\d\d):(\d\d)(..)/.match("12:50am") # md爲一個MatchData對象
puts "Hour is #$1, minute #$2"
puts "Hour is #{md[1]}, minute #{md[2]}"
5、匹配所有
regexp#match()只能匹配一次,如果想匹配所有要用regexp#scan()
用法示例:
"abcabcabz".scan(%r{abc}).each {|item| puts item} # 輸出2行abc
6、貪婪匹配vs懶惰匹配
這兩種匹配屬於標準正則表達式內容,與Ruby沒關,但新手如果不明白匹配時會發生莫名其妙的錯誤,所以特別總結一下。
- 貪婪匹配:儘可能多匹配,正則默認是貪婪匹配。例子:a.*b它將會匹配最長的以a開始,以b結束的字符串。對於aabab的匹配結果是aabab。
- 懶惰匹配:儘可能少匹配。例子:a.*?b對於aabab的匹配結果是aab和ab。
一般是在原來表達式結尾加?就由貪婪匹配變成了懶惰匹配。常用的懶惰限定符有(去年最後的問題就是貪婪匹配):
- ?重複任意次,但儘可能少重複
- +?重複1次或更多次,但儘可能少重複
- ??重複0次或1次,但儘可能少重複
- {n,m}?重複n到m次,但儘可能少重複
- {n,}?重複n次以上,但儘可能少重複