0

使用这段代码,它应该用它的 URL 替换一个 href 标记:

irb> s='<p><a href="http://localhost/activate/57f7e805827f" style="color:#F19300;font-weight:bold">Click here!</a></p>'
irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
=> "<p></p>"

此正则表达式失败(未找到 URL)。然后我转义<正则表达式中的字符,它可以工作:

irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^\<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/57f7e805827f</p>"

1:根据RubyMine的检查,这种逃逸应该是没有必要的。它是否正确?如果是这样,为什么>显然也没有必要逃脱?

2:之后在同一个 IRB 会话中,使用相同的字符串,原来的正则表达式突然也起作用了:

irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/57f7e805827f</p>"

这是因为再次$1调用时变量没有清除吗?gsub如果是这样,是故意行为还是 Ruby 正则表达式错误?

3:当我更改字符串并重新执行相同的命令时,$1只会在更改后gsub的字符串上调用两次后更改:

irb> s='<p><a href="http://localhost/activate/xxxxyyy" style="color:#F19300;font-weight:bold">Click here!</a></p>'
=> "<p><a href=\"http://localhost/activate/xxxxyyy\" style=\"color:#F19300;font-weight:bold\">Click here!</a></p>"
irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^\<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/57f7e805827f</p>"
irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^\<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/xxxxyyy</p>"

这是故意的吗?如果是这样,这背后的逻辑是什么?

4:作为替换字符,有的教程建议使用"#{$n}",有的建议使用'\n'。使用反斜杠变体,不会出现上述问题。为什么-两者之间有什么区别?

谢谢!

4

1 回答 1

2

$1包含最后一场比赛的第一次捕获。在您的示例中,它在匹配之前进行评估(实际上甚至在gsub调用之前),因此值$1固定为nil(因为您还没有匹配任何内容)。所以你总是能第一次捕捉到一场比赛,你甚至不需要改变你原来的正则表达式来第二次得到预期的结果:

s='<p><a href="http://localhost/activate/57f7e805827f" style="color:#F19300;font-weight:bold">Click here!</a></p>'

s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
# => "<p></p>"

s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
# => "<p>http://localhost/activate/57f7e805827f</p>"

您可以将一个块传递给gsub虽然,它在匹配后进行评估,例如

s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/){ $1 }
# => "<p>http://localhost/activate/57f7e805827f</p>"

这样,$1行为就如你所料。我喜欢总是使用命名的捕获,所以当我添加捕获时我不必跟踪数字,但是:

s.gsub(/<a href="(?<href>([^ '"]*))"([^>]*)?>([^<]*)<\/a>/){ $~[:href] }
# => "<p>http://localhost/activate/57f7e805827f</p>"
于 2012-10-28T12:54:04.960 回答