在Ruby脚本中,我使用string#gsub
生成一个用作正则表达式的字符串。此正则表达式必须与+
字符匹配,因此我使用\+
来逃避它。
此示例代码隔离了我的混淆源。在此代码中,我要创建的正则表达式是/a\+b/
。但是,当我使用#gsub
时,返回的正则表达式为/ab/
。
string = 'a\+b'
expected = Regexp.new(string)
actual = Regexp.new('x'.gsub('x', string))
# expected returns /a\+b/
# actual returns /ab/
我在Ruby文档中找不到关于#gsub
和+
字符的任何内容。任何人都可以帮助我理解产生这种结果的情况吗?
现在,为了使我的代码工作,我匹配\x2B
,+
字符的ANSI十六进制代码。有没有办法实现这个没有被混淆的东西?
提前致谢!
答案 0 :(得分:3)
我们忽略这里的Regexp.new
,因为它不是真正相关的 - 只有gsub
本身。
\+
将gsub
解释为\\d
的反向引用。来自the docs:
如果replacement是一个String,它将替换匹配的文本。它可能包含对
d
形式的模式捕获组的反向引用,其中\\k<n>
是组号,或n
,其中$&
是组名。如果它是双引号字符串,则两个反向引用都必须以额外的反斜杠开头。但是,在替换中,特殊匹配变量(例如\+
)不会引用当前匹配。
虽然不是很清楚(因为文档说“group number ”),$+
将替换全局变量$+
*;来自Ruby Quickref:
$~
:取决于'x'.gsub(/(x)/, 'a\+b') #=> "axb"
。最高组与上一次成功比赛匹配。
我们可以通过捕捉东西证明这一点:
\+
这表明"ab"
正在被正则表达式中的捕获所取代。由于您的模式中没有捕获(因为它是一个字符串),因此后引用将替换为空字符串,并且gsub
会得到"a\+b"
。
使用\+
可以正常工作,因为它实际上不是"a\+b".bytes #=> [97, 43, 98]
'a\+b'.bytes #=> [97, 92, 43, 98]
:
gsub
*有点,它在语义上是等价的,但是匹配全局变量本身实际上并没有设置,直到 {{1}}完成替换后 - 但是后引用是,当然,在更换之前设置。
答案 1 :(得分:1)
替换字符串\+
内部用于指代最后一个捕获组的值(例如,如果正则表达式包括3个捕获组\+
,则与{{1}相同})。如果您使用\3
的块形式,则不会执行这些替换:
gsub
答案 2 :(得分:0)
Regexp的union
方法通常用于从字符串(和/或Regexps)的组合创建正则表达式。因为它逃脱了这些字符串,所以它也很有用:
re = Regexp.union("a+b") # => /a\+b/
答案 3 :(得分:-1)
Regexp.new
会自动处理+
。
试试这个:
string = 'a+b'
expected = Regexp.new(string)
actual = Regexp.new('x'.gsub('x', string))
如果您有其他意思,请告诉我
对你问题的另一种解释让我想到了这一点:
string = 'a\\\+b'
expected = Regexp.new(string)
actual = Regexp.new('x'.gsub('x', string))