注:在某些浏览器或环境中\会显示成¥。
不要把字符串传给第一参数
因为一旦把字符串传给第一参数的话,就会依次进行下列处理过程
这会招致混乱。例如
p "foo".sub!("\\w+", 'bar') # => "bar"
它等同于下例
p "foo".sub!(/\w+/, 'bar') # => "bar"
即使使用单引号也会引起混乱,例如
p "\\".sub!('\\', 'bar') # => "bar"
=> -:1:in `sub!': invalid regular expression; '\' can't be last character: /\/ (RegexpError)
在上面的例子中,解释器试图编译正则表达式 `\'所以招致失败。下面的做法才是正确的
p "\\".sub!(/\\/, 'bar') # => "bar"
ruby 1.7 特性: 在1.7版中,不会进行第(2)个处理过程,因此将字符串传给第一参数时,不会将其编译为正则表达式,而是以字符串作pattern来进行搜索。(所以,就没必要担心第一参数的问题了。)但是在1.6版中,将
Regexp.escape(字符串)
传给第一参数时,
/#{ Regexp.escape(字符串) }/
有时(为了提高效率)会写成
/#{ Regexp.escape(字符串) }/o
这样。因为传递的是正则表达式,所以在1.6、1.7中会得到相同的处理。
不要将\1、\2等传给第二参数
因为一旦把字符串传给第二参数的话,就会依次进行下列处理过程
这会招致混乱。因此请您使用块。(传递块的话,就不会进行第(2)个步骤)例如
p "foo".sub!(/(\w+)/, "\\1bar") # => "foobar" p "foo".sub!(/(\w+)/, '\1bar') # => "foobar"
它等同于下例。
p "foo".sub!(/(\w+)/) { "#$1bar" } # => "foobar"
使用块的话,您还可以这样。
p "foo".sub!(/(\w+)/) { "#$1bar".upcase } # => "FOOBAR"
若不是用块的话,在执行sub!之前会首先进行upcase,所以是无效的。
p "foo".sub!(/(\w+)/, "\\1bar".upcase) # => "fooBAR"
总之,第二参数是为了书写简便而设的。请您参考下例。
p "\\".sub!(/(\\)/, "\1") # => "\001" p "\\".sub!(/(\\)/, "\\1") # => "\\" p "\\".sub!(/(\\)/, "\\\1") # => "\\\001" p "\\".sub!(/(\\)/, "\\\\1") # => "\\1" p "\\".sub!(/(\\)/, "\\\\\1") # => "\\\001" p "\\".sub!(/(\\)/, "\\\\\\1") # => "\\\\" p "\\".sub!(/(\\)/, "\\\\\\\1") # => "\\\\\001" p "\\".sub!(/(\\)/, '\1') # => "\\" p "\\".sub!(/(\\)/, '\\1') # => "\\" p "\\".sub!(/(\\)/, '\\\1') # => "\\1" p "\\".sub!(/(\\)/, '\\\\1') # => "\\1" p "\\".sub!(/(\\)/, '\\\\\1') # => "\\\\" p "\\".sub!(/(\\)/, '\\\\\\1') # => "\\\\" p "\\".sub!(/(\\)/, '\\\\\\\1') # => "\\\\1"
请注意,p方法把`\'输出成`\\'了。
另外,您不能这样。
p "foo".sub!(/(.*)/, "#{\\1}")
# => -:1: compile error in string expansion (SyntaxError)
在执行sub, gsub之前会首先对展开表达式#{..}进行解释。此时,\1仍旧是\1。因此使用块才是您正确的选择。
p "foo".sub!(/(.*)/) { "#$1" }