现在的位置: 首页 > 综合 > 正文

Ruby 正则表达式

2018年02月17日 ⁄ 综合 ⁄ 共 7781字 ⁄ 字号 评论关闭

练手:

  # \d
  # 数字。即[0-9]
  puts "aaa0" =~ /\d/  # 3 匹配数字
  puts /\d/ =~ "abc2"  # 3
  puts "kkmm1" =~ /\d/ # 4 匹配数字

  # [\u{4e00}-\u{9fff}]
  # 中文
  puts "abcdef我熬啊" =~ /[\u{4e00}-\u{9fff}]/u   #6  匹配中文
  puts "abcdef我熬啊" =~ /\p{Han}/u  # 6

  # \w
  # 字母和数字。等同于[0-9A-Za-z]。
  puts "-=123a" =~  /\w/ # 2 匹配字母
  puts "-=a3a" =~  /\w/ # 2 匹配字母   

  # \s
  # 空字符。相当于[ \t\n\r\f]
  puts "aaa bbb" =~ /aa\s/ # 1
  puts "aaa bbb" =~ /\s/ # 3

  # ^
  # 行首。与字符串的头部或换行符之后的位置相匹配。
  # \A
  # 字符串头部。与^不同的是,它不受有无换行符的影响 。
  puts "abcd\nefghg" =~ /^e/ # 5
  puts "1\n2\n3\n4" =~ /^3/  # 4
  puts "1\n2\n3\n4" =~ /\A1/ # 0
  puts "abcd\nefghg" =~ /\A/ # 0

  # $
  # 行尾。与字符串的尾部或换行符之前的位置相匹配。不包括换行符本身。
  # \Z
  # 字符串尾部。若字符串以换行符结尾,则匹配换行符前的位置。
  puts "abcd\nefghg" =~ /g$/ # 9
  puts "1\n2\n3\n4" =~ /3$/  # 4
  puts "1\n2\n3\n4" =~ /4\Z/ # 6
  puts "abcd\nefghg" =~ /\Z/ # 10

  # .
  # 匹配除换行符以外的任意一个字符。使用正则表达式选项 m(多行模式。请参考正则表达式字面值) 时,则匹配包括换行符在内的任意一个字符。在匹配多字节字符的正则表达式中,则匹配一个字(非单字节)。
  # 当遇到不完整的多字节字符的一部分(无法判断该字符是多字节字符?二进制?还是ASCII)时,也不会匹配。
  puts /./e =~ "CV--aa" # 0
  puts /./ =~ "あ"  # 0
  /a.*b/.match("a123bcab") #=><MatchData "a123bcab:>

  # \b
  # 在字符范围描述符之外时表示词边界(匹配从\w到\W)。在字符范围描述符之内时表示退格符(0x08)。
  puts "232342eaaabbbddd43452532543" =~ /b/ # 10

  # 从头取出3位数字(数字必须相连)。
  str = "123456 789"
  puts str.scan(/\G\d\d\d/) {|m| p m }

  # [ ]
  # 指定字符范围。请参考字符范围
  puts "1445345abc" =~ /[a-z]/

  # *
  # 前面元素至少出现0次。尽可能匹配较长的部分。
  # *?
  # 负责指定数量(quantifiers)。表示前面元素至少出现0次(尽量匹配短的部分)
  # +
  # 负责指定数量(quantifiers)。表示前面元素至少出现1次
  # +?
  # 负责指定数量(quantifiers)。表示前面元素至少出现1次(尽量匹配短的部分)

  # {m}
  # {m,}
  # {m,n}
  # 指定元素重复出现的次数(interval quantifier)。分别表示前面元素重复出现
  # m 次
  # 至少 m 次
  # 至少 m 次,至多 n 次
  # {,n} 或 {,} 将导致匹配失败。
  str = "foofoofoo"
  p str[/(foo){1}/]   # => "foo"
  p str[/(foo){2,}/]  # => "foofoofoo"
  p str[/(foo){1,2}/] # => "foofoo"

  # 正则表达式 ?, *, + 分别等同于 {0,1}, {0,} {1,} 。
  # {m}?
  # {m,}?
  # {m,n}?
  # 指定元素重复出现的次数(interval quantifier)。分别表示前面元素重复出现
  # m 次
  # 至少 m 次
  # 至少 m 次,至多 n 次
  # (尽量匹配短的部分)。
  str = "foofoofoo"
  p str[/f{1}?/] # f
  p str[/(o){2,8}?/] # f

  # ?
  # 负责指定数量(quantifiers)。表示前面元素至多出现1次。
  # ??
  # 负责指定数量(quantifiers)。表示前面元素至多出现1次(尽量匹配短的部分)
  # |
  # 选择(alternative)。
  # ( )
  # 正则表达式的群组化。与括号中的正则表达式相匹配的字符串将被保存下来,供后方参考使用。
  p /(ab)+/=~"123abab"
  p /(ab)+/.match("123abab") #=><MatchData "abab" 1:"ab">
  # \1, \2 ... \n
  # 后方参考(back reference)。请参考后方参考。
  p /((foo)bar)foobarfoo/
  re = /(foo|bar|baz)\1/
  p re =~ 'foofoo'   # => 0
  p re =~ 'barbar'   # => 0
  p re =~ 'bazbaz'   # => 0
  p re =~ 'foobar'   # => nil

  # (?# )
  # 注释。括号中的任意字符串将被忽视。

  # (?: )
  # 不具备后方参考功能的群组化。它不为\1,\2(或$1,$2)提供服务,是一种单纯的群组功能。
  /(cba)/ =~ "abccba"
  p $1  # cba

  /(?:abc)/ =~ "abc"
  p $1

1.建立正则表达式

使用”//” reg=/ru\/by/ 需要对转义字符转义
使用类方法Regexp.new reg=Regexp.new(“ru/by”) 不需要对转义字符转义
使用%r reg=%r(ru/by) 不需要对转义字符转义

2.正则表达式的一般匹配

  1. /ruby/ =~ "ruby string" #=>0 返回匹配成功的起始位置
  2. /ruby/.match("string # 返回匹配成功的字符串

3.匹配行首行尾和字符串首尾

若字符串中有换行符,行尾就是换行符的前面

  1. ^ 匹配行首 /^ruby/=~"rubystring" #=>0 /^ruby/=~"string\nruby" #=>7
  2. $ 匹配行尾 /ruby$/=~"stringruby" #=>6 /ruby$/=~"stringruby/string" #=>6
  3. \A 匹配字符串首 /\Aruby/=~"rubystring" #=>0 /\Aruby/=~"string\nrubystring" #=>nil
  4. \Z 匹配字符串尾 /ruby\Z/=~"string\nruby" #=>7 /ruby\Z/=~"stringruby\nstring" #=>nil

4.指定匹配范围和多选

  1. [ab] 匹配a或b /[ab]/=~"stringa" #=>6
  2. [adf] 匹配a、d或f /[adf]/=~"stringd" #=>6
  3. [a-z] 匹配a到z /[a-z]/=~"123r" #=>3
  4. [A-Za-z] 匹配A到Z和a到z /[A-Za-z]/=~"123D321" #=>3
  5. [0-9] 匹配0到9 /[0-9]/=~"abc4ef" #=>3

在[ ]内加入^表示匹配除括号内指定的字符外

[^abc] 匹配除abc之外的字符
/[^abc]/=~"abccb"     #=>nil
/[^abc]/=~"acdf"      #=>2

使用”|”来添加候选字符

/12a|b/.match("123bc")    #=gt;<MatchData "12b">
/12a|b|c/.match("123cd")  #=gt;<MatchData "12c">

5.匹配任意字符

匹配除换行符外地任意字符

/./=~"abc"     #=>0

6.反斜杠字母

  1. \s 匹配空白、换行符、定位字符、换页符 /a\sc/=~"abca c" #=>3
  2. \S 匹配除空白、换行符、定位符、换页符之外的字符 /a\Sc/=~"a\ncabc" #=>3
  3. \d 匹配数字 /a\dc/=~"abca1c" #=>3
  4. \D 匹配除数字之外的字符 /a\Dc/=~"a1cabc" #=>3
  5. \w 匹配数字、字母和"_" /a\wc/=~"a&cabc" #=>3
  6. \W 匹配除数字、字母和"_"之外的字符 /a\Wc/=~"abca&c" #=>3
  7. \b 匹配单词的开始或结尾 /\bis/=~"this ist" #=>5 /is\b/=~"this ist" #=>2
  8. \B 与\b相对 /\Bis/=~"this ist" #=>2 /is\B/=~"this ist" #=>5

7.转义字符的转义

在转义字符”^”,”$”,”["等前面加上"\",就能对转义字符进行转义来表示它自己

/abc\$/=~"abc"   #=>nil
/abc\$/=~"abc$"  #=>0

通过quote方法来将转义字符变成普通字符

reg1=Regexp.new("a*b")
reg2=Regexp.new(Regexp.quote("a*b"))
reg1=~"123a*b"   #=>nil
reg2=~"123a*b"   #=>3

8.反复的匹配

  1. * 出现0次或以上 /a*b/.match("123aaab") #=><MatchData "aaab"> /a*b/.match("123b") #=><MatchData "b">
  2. + 出现1次或以上 /a+b/.match("123aaab") #=><MatchData "aaab"> /a+b/.match("123b") #=>nil /a+b/.match("123ab") #=><MatchData "ab">
  3. ? 出现0次或1次 /a?b/=~"123aaab" #=>5 /^a?b/=~"aaab" #=>nil /.?b/.match("123b") #=><MatchData "3b">

ruby的正则表达式匹配时是贪婪匹配,即匹配时尽可能匹配更多的字符

/a.*b/.match("a123bcab") #=><MatchData "a123bcab:>

可通过添加"?"来变成不贪婪匹配

*? 0次或以上的不贪婪匹配
+? 1次或以上的不贪婪匹配
/a.*?b/.match("a123bcab") #=><MatchData "a123b">

使用()群组来反复

/(ab)*/=~"123abab"       #=>0
/(ab)*/.match("123abab") #=><MatchData "" 1:nil>
/(ab)+/=~"123abab"       #=>3
/(ab)+/.match("123abab") #=><MatchData "abab" 1:"ab">

使用{}来为制定的字符取得多次匹配

  1. /a{n}/ 匹配n个a /a{3}/.match("123aaab") #=><MatchData "aaa">
  2. /a{n,} 匹配n或n以上个a /a{3,}/.match("123aaaab") #=><MatchData "aaaa">
  3. /a{n,m} 匹配n到m个a /a{1,3}b/=~"123b" #=>nil /a{1,3}b/=~"123ab" #=>3 /a{1,3}b/=~"123aab" #=>3 /a{1,3}b/=~"123aaab" #=>3 /a{1,3}b/=~"123aaaab" #->nil

9.正则表达式的选项

  1. 通过直接在添加"/.../"后面,如/Ab/i
    1. i 忽略大小写 /ab/i=~"12AB" #=>2
    2. m 多行匹配,能让"."匹配换行符 /a.b/m=~"12a\nbc" #=>2
    3. x 忽略空白、换行符,并忽略"#"后面的字符,这时可使用#来添加注释了 /a b/=~"12ab" #=>nil /a b/x=~"12ab" #=>2 /a b#def/x.match("12abdef") #=><MatchData "ab">
    4. s,e,u,n 指定字符编码,s是Shift-JIS,e是EUC-JP, u是UTF-8,n是none即不考虑字符编码
  2. 通过在字符前面添加选项,选项后面的字符都被选项影响, 而选项前面的字符则不受影响
    1. (?i) /A(?i)bc/=~"ABC" #=>0 /A(?i)bc/=~"abc" #=>nil /A(?i)b(?-i)c/=~"AbC #=>nil /A(?i)b(?-i)c/=~"ABc" #=>0
    2. 类似还有(?m),(?x),(?-i)表示不能忽略大小写, (?-m)表示不能忽略换行符,(?-x)表示不能忽略空白
  3. 通过将字符串写入选项内
    1. (?i:) /A(?i:bc)/=~"ABC" #=>0
    2. 同样,还有(?-i:),(?m:),(?-m:),(?x:),(?-x:)

10.添加注释

除了通过上面所讲,使用x选项来添加注释,还可以使用(?#)

/ab(?#def)/=~"123ab"    #=>3
/\d-(?#这里的"-"不是指范围)\d/=~"ab1-2"  #=>2

11.回溯参照(backreference,反向引用)

回溯参照用来取出字符串中匹配成功的一部分

  1. 与正则表达式中的()中所匹配的字符串可用$1,$2,,$3……来取出 取出顺序是从左往右,从外向内 /(a)(.)(b)/.match("123aeb") #=><MatchData "acb" 1:"a" 2:"e" 3:"b"> p $1 #=>"a" p $2 #=>"e" p $3 #=>"c" /((.)(a))/.match("123abc") #=><MatchData "3a" 1:"3a" 2:"3" 3:"a"> p $1 #=>"3a" p $2 #=>"3" p $3 #->"a"
  2. 取出与正则表达式所匹配的字符,匹配的字符的前面,匹配字符的后面 分别用$&,$`(1旁边),$' /ab/=~"123ab456" #=>3 p $& #=>"ab" p $` #=>"123" p $' #=>"456"
  3. 取出MatchData,用$~ /(a)b/=~"123ab" #=>3 p $` #=>"123" p $' #=>"" p $& #=>"ab" p $~ #=><MatchData "ab" 1:"a">
  4. 用形如"\num"来匹配群组1,群组2,群组3……群组num的字符 /a(b)\1/=~"abc" #=>nil /a(b)\1/=~"abb" #=>0 /(a)(b)\1\2/=~"abaa" #=>nil /(a)(b)\1\2/.match("123abab") #=><MatchData "abab" 1:"a" 2:"b"> /(a)(b)\2/=~"abb" #=>0 /((a)(b))\1/.match("123abab") #=><MatchData "abab" 1:"ab" 2:"a" 3:"b"> /(a|b)\1/=~"ab" #=>nil /(a|b)\1/=~"ba" #=>nil /(a|b)\1/=~"aa" #=>0 /(a|b)\1/=~"bb" #=>0 若要在\num后面添加数字,则必须得给\num添加括号 /a(b)(\1)2/=~"ab12" #=>nil /a(b)(\1)2/=~"abb2" #=>0
  5. 使用索引 mat1=/.a/.match("123a") #=><MatchData "3a"> p mat1[0] #=>”3a” p mat1[1] #nil mat2=/(.)a/.match(“123a”) #=><MatchData “3a” 1:”3″> p mat2[0] #=>”3a” p mat2[1] #=>”3″ p mat2[2] #=>nil
  6. 若只想有群组的功能,而没有回溯参照的功能,则可以使用(?:) /(a)(?:b)(c)/.match(“123abcd”) #=><MatchData “abc” 1:”a” 2:”c”>

12.(?!exp)和(?=exp)

  1. (?!exp) 匹配后缀不是exp /ab(?!c)/=~"abc" #=>nil /ab(?!c)/=~"abe" #=>0
  2. (?=exp) 匹配后缀为exp /ab(?=c)/=~"abc" #=>0 /ab(?=c)/=~"abe" #=>nil

13.sub方法和gsub方法

sub方法和gsub方法都是用来取代字符串中字符的方法,
第一个参数指定匹配样式,第二个参数指定想要代入的字符串。
sub方法只会取代第一个匹配成功的字符串,
而gsub方法会取代所有匹配成功的字符串
  1. sub方法,sub!方法 str="abc\n123\456" str.sub(/\n/,'d') #=>"abcd123\n456"
  2. gsub方法,gsub!方法 str="abc\n123\n456" str.gsub(/\n/,'d') #=>"abcd123d456"

sub方法和gsub方法也可以传入区块

str="ab12ac34ad"
str.gsub(/a./){|mat|
  print "string ",mat,"\n"
  }
#=>
string ab
string ac
string ad

14.scan方法

scan方法会查找字符串中所有匹配的字符,并以数组返回
"12ab34ac56ad".scan(/a./)   #=>["ab","ac","ad"]
scan方法也可以传入区块
"12ab34ac56ad".scan(/a./){|mat|
  print "string ",mat,"\n"
  }
#=&gt
string ab
string ac
string ad
当正则表达式中含有(),则匹配成功的部分会以数组的形式传入区块
"12ab34ac56ad".scan(/(a)(.)/){|mat|
  print mat
  }
#=>
["a","b"]
["a","c"]
["a","d"]
若区块中的变量和正则表达式中的()一样多式,则不会传入数组
"12ab34ac56ad".scan(/(a)(.)/){|m,n|
  print n," after ",m,"\n"
  }
#=>
b after a
c after a
d after a

15.正则表达式的条件判断

if /reg/ =~ "string"
  匹配成功时的动作
else
  匹配失败时的动作
end

16.# Regexp .match(text)

  md = /(\d\d):(\d\d)(..)/.match("12:50am")
  puts "Hour is #$1, minute #$2"
  puts "Hour is #{md[1]}, minute #{md[2]}"
  # Regexp .quote(text) | .escape(text)
  # String .index(Regexp)  | =~

  17.# String .scan(Regexp)

  "abcabcabz".scan(%r{abc}).each {|item| puts item} # 输出2行abc
  puts "2010-11-22 2022-08-25".scan(/\d{4}-\d{2}-\d{2}/)
  puts "2010-11-22 2022-08-25".scan(/(\d{4})-(\d{2})-(\d{2})/)

  18.#String .slice(Regexp)

  string = "Date: 2012-12-23"
  regex = /\d{4}-\d{2}-\d{2}/
  p string.slice(regex) # 2012-12-23

 19. #String.split(Regexp)

  p "2012-12-23".split(/-/)

  20.# String.sub | .gsub(Regexp,String)

  str = "ABDADA"
  p str.sub(/A/, "*")   #返回"*BDADA"
  p str.gsub(/A/, "*") #返回"*BD*D*"

抱歉!评论已关闭.