正則表達(dá)式
下面就來(lái)講講ruby支持的正則表達(dá)式符號(hào)(元字符)。
有這么個(gè)規(guī)則:
- 不帶\的數(shù)字和字母不是元字符
- 帶\的符號(hào)也不是元字符
下文中出現(xiàn)的“匹配多字節(jié)字符的正則表達(dá)式”是指,通過(guò)使用 $KCODE 進(jìn)行設(shè)定,或顯式地使用漢字選項(xiàng)(請(qǐng)參考 正則表達(dá)式字面值 )等方式進(jìn)行的匹配多字節(jié)字符的正則表達(dá)式。
-
^
行首。與字符串的頭部或換行符之后的位置相匹配。
-
$
行尾。與字符串的尾部或換行符之前的位置相匹配。不包括換行符本身。
ruby 1.8 特性 :以前,只匹配字符串尾部換行符前的位置,現(xiàn)在則擴(kuò)大到字符串的尾部。 trap::Regexp
p "\n".gsub(/$/, "o") => "o\n" (1.6) => "o\no" (1.8)
-
.
匹配除換行符以外的任意一個(gè)字符。使用正則表達(dá)式選項(xiàng) m(多行模式。請(qǐng)參考 正則表達(dá)式字面值 ) 時(shí),則匹配包括換行符在內(nèi)的任意一個(gè)字符。在匹配多字節(jié)字符的正則表達(dá)式中,則匹配一個(gè)字(非單字節(jié))。
當(dāng)遇到不完整的多字節(jié)字符的一部分(無(wú)法判斷該字符是多字節(jié)字符?二進(jìn)制?還是ASCII)時(shí),也不會(huì)匹配。
p /./e =~ "あ"[0,1] # => nil
-
\w
字母和數(shù)字。等同于
[0-9A-Za-z]
。若為匹配多字節(jié)字符的正則表達(dá)式時(shí),則也會(huì)匹配日語(yǔ)的全角字符。
-
\W
非字母和數(shù)字。
\w
以外的單個(gè)字符。 -
\s
空字符。相當(dāng)于
[ \t\n\r\f]
-
\S
非空字符。
[ \t\n\r\f]
以外的單個(gè)字符。 -
\d
數(shù)字。即
[0-9]
-
\D
非數(shù)字
-
\A
字符串頭部。與
^
不同的是,它不受有無(wú)換行符的影響 。 -
\Z
字符串尾部。若字符串以換行符結(jié)尾,則匹配換行符前的位置。
ruby 1.8 特性 :以前,只匹配字符串尾部換行符前的位置,現(xiàn)在則擴(kuò)大到字符串的尾部。 trap::Regexp
p "\n".gsub(/\Z/, "o") => "o\n" (1.6) => "o\no" (1.8)
-
\z
字符串結(jié)尾。與$以及\Z不同的是,它不受有無(wú)換行符的影響。
-
\b
在字符范圍描述符之外時(shí)表示詞邊界(匹配從\w到\W)。在字符范圍描述符之內(nèi)時(shí)表示退格符(0x08)。
-
\B
非詞邊界
-
\G
在上次成功匹配的地方(之后)進(jìn)行匹配(不留余地)。只有在首次使用時(shí)才會(huì)匹配到頭部(與\A相同)。
可以用在 scan 和 gsub 中。當(dāng)您想在上次匹配的地方之后再進(jìn)行匹配的話,可以使用。
舉個(gè)簡(jiǎn)單(沒(méi)什么用)的例子。
# 從頭取出3位數(shù)字(數(shù)字必須相連)。 str = "123456 789" str.scan(/\G\d\d\d/) {|m| p m }
-
[ ]
指定字符范圍。請(qǐng)參考 字符范圍
。
-
*
前面元素至少出現(xiàn)0次。盡可能匹配較長(zhǎng)的部分。
-
*?
負(fù)責(zé)指定數(shù)量(quantifiers)。表示前面元素至少出現(xiàn)0次(盡量匹配短的部分)
-
+
負(fù)責(zé)指定數(shù)量(quantifiers)。表示前面元素至少出現(xiàn)1次
-
+?
負(fù)責(zé)指定數(shù)量(quantifiers)。表示前面元素至少出現(xiàn)1次(盡量匹配短的部分)
-
{m}
-
{m,}
-
{m,n}
指定元素重復(fù)出現(xiàn)的次數(shù)(interval quantifier)。分別表示前面元素重復(fù)出現(xiàn)
- m 次
- 至少 m 次
- 至少 m 次,至多 n 次
{,n}
或{,}
將導(dǎo)致匹配失敗。str = "foofoofoo" p str[/(foo){1}/] # => "foo" p str[/(foo){2,}/] # => "foofoofoo" p str[/(foo){1,2}/] # => "foofoo"
正則表達(dá)式
?
,*
,+
分別等同于{0,1}
,{0,}
{1,}
。 -
{m}?
-
{m,}?
-
{m,n}?
指定元素重復(fù)出現(xiàn)的次數(shù)(interval quantifier)。分別表示前面元素重復(fù)出現(xiàn)
- m 次
- 至少 m 次
- 至少 m 次,至多 n 次
(盡量匹配短的部分)。
-
?
負(fù)責(zé)指定數(shù)量(quantifiers)。表示前面元素至多出現(xiàn)1次。
-
??
負(fù)責(zé)指定數(shù)量(quantifiers)。表示前面元素至多出現(xiàn)1次(盡量匹配短的部分)
-
|
選擇(alternative)。
-
( )
正則表達(dá)式的群組化。與括號(hào)中的正則表達(dá)式相匹配的字符串將被保存下來(lái),供后方參考使用。
-
\1
,\2
...\ n
后方參考(back reference)。請(qǐng)參考 后方參考 。
-
(?# )
注釋。括號(hào)中的任意字符串將被忽視。
-
(?: )
不具備后方參考功能的群組化。它不為\1,\2(或 $1 , $2 )提供服務(wù),是一種單純的群組功能。
/(abc)/ =~ "abc" p $1 => "abc" /(?:abc)/ =~ "abc" p $1 => nil
-
(?= )
先行(lookahead)。使用模式(pattern)指定位置(不留間隔)
(?=re1)re2
表示將匹配同時(shí)符合re1和re2的要求的字符串。
re1(?=re2)
という山附は、稿に re2 とマッチする矢機(jī)誤が魯く、正則表達(dá)式 re1 です。
p /foo(?=bar)/ =~ "foobar" # => 0 p $& # => "foo" (bar の嬸尸の攫鼠はない)
-
(?! )
否定先行(negative lookahead)。使用否定的模式(pattern)來(lái)指定位置(不留間隔)
(?!re1)re2
該正則表達(dá)式表示,匹配re1但不匹配re2。
# 除000以外的3位數(shù)字 re = /(?!000)\d\d\d/ p re =~ "000" # => nil p re =~ "012" # => 0 p re =~ "123" # => 0 # C語(yǔ)言標(biāo)識(shí)符 (首位是[A-Za-z_]然后是[0-9A-Za-z_]的字符串) /\b(?![0-9])\w+\b/
-
(?> )
禁用 回縮功能 。
該功能尚處于試驗(yàn)階段。將來(lái)有可能被停用,請(qǐng)您注意使用。特別是不要在廣義庫(kù)中使用。
-
(?ixm-ixm)
正則表達(dá)式中的i選項(xiàng)、x選項(xiàng)、m選項(xiàng)的開關(guān)。請(qǐng)您參考 正則表達(dá)式字面值 來(lái)了解選項(xiàng)的詳細(xì)內(nèi)容。
re = /A(?i)a(?-i)A/ p re =~ "AaA" # => 0 p re =~ "AAA" # => 0 p re =~ "AAa" # => nil
-
(?ixm-ixm: )
括號(hào)中的i選項(xiàng)、x選項(xiàng)、m選項(xiàng)的開關(guān)。在括號(hào)范圍內(nèi)有效。
re = /A(?i:a)A/ p re =~ "AaA" # => 0 p re =~ "AAA" # => 0 p re =~ "AAa" # => nil
后方參考
正則表達(dá)式 \1 \2 ... \n 表示后方參考。\n表示將匹配第n個(gè)括號(hào)(正則表達(dá)式的()表示群)的內(nèi)容保存起來(lái),供后面使用。
/((foo)bar)\1\2/
和
/((foo)bar)foobarfoo/
是一樣的。
例:
re = /(foo|bar|baz)\1/ p re =~ 'foofoo' # => 0 p re =~ 'barbar' # => 0 p re =~ 'bazbaz' # => 0 p re =~ 'foobar' # => nil
對(duì)應(yīng)的括號(hào)必須位于后方參考表達(dá)式的左側(cè)。
若后方參考表達(dá)式位于對(duì)應(yīng)的括號(hào)中時(shí),匹配常常會(huì)失敗。當(dāng)后方參考表達(dá)式中的數(shù)字是1位,且沒(méi)有對(duì)應(yīng)的括號(hào)時(shí),匹配也將失敗。
p /(\1)/ =~ "foofoofoo" # => nil p /(foo)\2/ =~ "foo\2" # => nil
雖然可以指定2位以上的后方參考表達(dá)式,但是不要把它同 反斜線表示法 的\nnn(對(duì)應(yīng)于8進(jìn)制數(shù)nnn的字符)混為一談。當(dāng)數(shù)字只有1位時(shí),通常是后方參考表達(dá)式。當(dāng)指定了一個(gè)超過(guò)2位的數(shù)字時(shí),若沒(méi)有對(duì)應(yīng)括號(hào)的話,則被看作是8進(jìn)制代碼。
相反地,若在正則表達(dá)式中使用1位的8進(jìn)制代碼時(shí),必須以0打頭,例如\01等(不可能存在形如\0這樣的后方參考表達(dá)式,因此不會(huì)混淆)。
p /\1/ =~ "\1" # => nil # 無(wú)對(duì)應(yīng)括號(hào)的后方參考 p /\01/ =~ "\1" # => 0 8 進(jìn)制代碼 p /\11/ =~ "\11" # => 0 8 進(jìn)制代碼 # 8 進(jìn)制代碼 (因?yàn)闆](méi)有對(duì)應(yīng)括號(hào)) p /(.)\10/ =~ "1\10" # => 0 # 后方參考 (因?yàn)橛袑?duì)應(yīng)的括號(hào)) p /((((((((((.))))))))))\10/ =~ "aa" # => 0 # 8 進(jìn)制代碼 (因?yàn)闆](méi)有像"\0" + "8" -> \08 這樣的8進(jìn)制代碼) p /(.)\08/ =~ "1\0008" # => 0 # 如果想在后方參考表達(dá)式之后插入數(shù)字的話,就必須使用括號(hào)加以分隔。 p /(.)(\1)1/ =~ "111" # => 0
字符范圍
正則表達(dá)式 [] 負(fù)責(zé)指定字符范圍。這將匹配 [] 內(nèi)列出的任何一個(gè)字符。
例如/[abc]/表示只要匹配"a", "b", "c"中任何一個(gè)即可。也可以按照ASCII代碼順序,在連續(xù)的字符串之間插入“-”后寫成/[a-c]/也是一樣的效果。另外,若頭上是“^”的話,表示要匹配指定字符之外的一個(gè)字符。
若“^”不在頭上的話,表示匹配該字符本身。同時(shí),當(dāng)“-”出現(xiàn)在頭或尾上時(shí),表示匹配該字符本身。
p /[a^]/ =~ "^" # => 0 p /[-a]/ =~ "-" # => 0 p /[a-]/ =~ "-" # => 0 p /[-]/ =~ "-" # => 0
空的字符范圍將引發(fā)錯(cuò)誤。
p /[]/ =~ "" p /[^]/ =~ "^" # => invalid regular expression; empty character class: /[^]/
當(dāng)“]”出現(xiàn)在頭上(或否定的“^”之后)時(shí),表示“]”本身,而并非字符范圍的結(jié)尾。
p /[]]/ =~ "]" # => 0 p /[^]]/ =~ "]" # => nil
可以使用反斜線對(duì)"^", "-", "]" 以及 "\\"(反斜線)進(jìn)行轉(zhuǎn)義,使其匹配該字符本身。
p /[\^]/ =~ "^" # => 0 p /[\-]/ =~ "-" # => 0 p /[\]]/ =~ "]" # => 0 p /[\\]/ =~ "\\" # => 0
在[]中可以使用 反斜線表示法 以及正則表達(dá)式\w, \W, \s, \S, \d, \D (這些都是表示字符范圍的簡(jiǎn)寫法)。
請(qǐng)注意,下列包含否定意味的字符范圍也將匹配換行符(正則表達(dá)式 \W,\D 也是如此)。
p /[^a-z]/ =~ "\n" # => 0
字符范圍中也可以使用下列特殊的表達(dá)法,但是,將來(lái)這些表達(dá)法是否會(huì)繼續(xù)得到支持還未可知(所以此處從略,欲知詳情請(qǐng)參考 grep(1) 的手冊(cè))。
[:alnum:] 數(shù)字和字母 0-9a-zA-Z [:alpha:] 字母 a-zA-Z [:blank:] 空白類 [:cntrl:] 控制字符 [:digit:] 數(shù)字 [:graph:] 除空白以外的可打印可視字符 [:lower:] 小寫字母 [:print:] 可視字符 [:punct:] 符號(hào) [:space:] 空白字符 [:upper:] 大寫字母 [:xdigit:] 16進(jìn)制字符
例: (包括"[]"在內(nèi),"[:...:]"表示1個(gè)字符。并非文字類的"[]")
p /[[:alnum:]][[:cntrl:]]/ =~ "a\x01" # => 0
注: 全角字符不在考慮范圍之內(nèi)。即使指定讓正則表達(dá)式對(duì)漢字進(jìn)行匹配時(shí),[:alpha:]等也不會(huì)匹配全角的字母。
p /[[:alpha:]]/e =~ "A" # => nil
回縮(backtrack)
用特殊括號(hào)(?> )將正則表達(dá)式括起來(lái)后,與該正則表達(dá)式相匹配的字符串中的回縮功能就將失效。舉例如下。
例如在通常的正則表達(dá)式中
p /(a*)ab/ === 'aaab'
是匹配的。該匹配過(guò)程如下所示。
- 正則表達(dá)式 a* 從索引0開始匹配3個(gè)a
- 正則表達(dá)式 a 匹配失敗
- 正則表達(dá)式 a* 將匹配部分稍稍“縮小”一下,匹配2個(gè)a(使用了回縮功能)
- 正則表達(dá)式 a 與字符a匹配
- 正則表達(dá)式 b 與字符b匹配
- 正則表達(dá)式 a* 從索引0開始匹配3個(gè)a
- 正則表達(dá)式 a 匹配失敗
- a* 想把匹配部分回縮一下,但由于特殊括號(hào)的作用,回縮功能失效。
- 正則表達(dá)式 a* 從索引1開始匹配2個(gè)a
接下來(lái)的匹配都不成功,最終導(dǎo)致整體匹配失敗。
簡(jiǎn)單說(shuō)來(lái),通常的正則表達(dá)式是“貪婪型的匹配”,而(?> )則是“超貪婪型的匹配”,因?yàn)樗坏┢ヅ涑晒蜎Q不放手。
范例
為了便于您拷貝使用,我們將其代入到以$re_開頭的全局變量中。
數(shù)值
-
浮點(diǎn)數(shù)(包括整數(shù))
$re_float = /[-+]?(?:[0-9]+(\.[0-9]*)?|(\.[0-9]+))([eE][-+]?[0-9]+)?/ p $re_float =~ "1.23" # => 0 p $&.to_f # => 1.23 p $re_float =~ ".23" # => 0 p $&.to_f # => 0.23 p $re_float =~ "1.23e1" # => 0 p $&.to_f # => 12.3 p $re_float =~ "1.23e-1" # => 0 p $&.to_f # => 0.123
用逗號(hào)將數(shù)字劃分成3位一組的形式
-
方法1:使用回行和先行的方法(回行(lookbehind)需要Oniguruma庫(kù)的支持)
p "tone of 12345Hz".gsub(/(?<=\d)(?=(?:\d\d\d)+(?!\d))/, ',') => ruby 1.8.0 (2003-08-07) [i586-linux] "tone of 12,345Hz"
-
方法2:只使用先行的方法
p "tone of 12345Hz".gsub(/(\d)(?=(?:\d\d\d)+(?!\d))/, '\1,') => ruby 1.8.0 (2003-08-07) [i586-linux] "tone of 12,345Hz"
-
方法3:不使用先行的方法
s = "tone of 12345Hz" nil while s.gsub!(/(.*\d)(\d\d\d)/, '\1,\2') p s => ruby 1.8.0 (2003-08-07) [i586-linux] "tone of 12,345 Hz"
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
