使用Ruby,我正在编写一个正则表达式,我需要能够删除括号中出现的任何冒号。我明白我可以使用
"This is a (string :)".sub!(/\([^\)]*:/, '')
要做到这一点,但问题是这个函数也会随之删除上下文。有没有办法指定我只想删除冒号而不是整个匹配表达式?
答案 0 :(得分:2)
因此,一些正则表达式引擎支持所谓的前瞻和后视匹配,这些匹配将匹配但不会消耗字符。 Ruby确实支持前瞻,但不支持后瞻(以高性能方式更难以实现),这意味着您可以非常轻松地使用sub
并删除在右括号之前的冒号,但仅不确定它是在一个左括号之后:
string = 'This is a (string :)'
string.sub /:(?=\))/, ''
# => 'This is a (string )'
另一种方法是使用子模式捕获(在正则表达式中使用分组时会自动发生)重建字符串而不包含不需要的部分,在本例中为冒号:
string.sub /(\([^:]+):\)/, '\1)'
\1
是对第一组中匹配内容的反向引用,第一组由未转义的括号分隔。你可以在这里看到我没有在第二组中捕获右括号,而是选择将其包含在替换中。这种情况在这种情况下效果很好,因为它不会改变,但是如果你不知道冒号会出现在括号括起的内容的末尾,你需要第二组:
string.sub /(\([^:]+):([^)]+\))/, '\1\2'
答案 1 :(得分:1)
之前的答案主要用于删除paren组中的单个冒号,但是遇到像'(thing:foo:bar)`这样的倍数有问题。使用lookbehind和lookahead来做内部断言会很好,但ruby(和大多数regexp引擎)不支持lookbehind中的非确定性长度模式。
irb> s = 'x (a:b:c) : (1:2:3) y'
=> "x (a:b:c) : (1:2:3) y"
irb> s.gsub /(?<=\([^\(]*):(?=[^\)]*\))/, ''
SyntaxError: (irb):10: invalid pattern in look-behind: /(?<=\([^\(]*):(?=[^\)]*\))/
from /Users/dbenhur/.rbenv/versions/1.9.2-wp/bin/irb:12:in `<main>'
您可以改为使用gsub的块形式捕获paren封闭的组,然后从每个匹配中删除冒号:
irb> s.gsub(/\([^\)]*\)/) {|m| m.delete ':'}
=> "x (abc) : (123) y"
答案 2 :(得分:0)
在正则表达式中,您可以使用'(\()(:)(\))', \1\3.
我不熟悉Ruby。基本上你做的是你有3组,从这三组( : and )
你摆脱了第二组,:
。
我在Notepad ++中对它进行了测试,但它确实有效。
我认为这称为:正则表达式反向引用
干杯。
答案 3 :(得分:0)
如果你可以假设所有的括号都会像你的例子一样平衡对,那么这应该是你所需要的:
"This is a (string :)".gsub!(/:(?=[^()]*\))/, '')
如果前瞻成功找到一个关闭的paren而没有先看到一个开口paren,则冒号必须在(...)
序列内。注意我是如何排除开场线以及结束线的;这是至关重要的。