负面看中间的东西背后

时间:2013-01-08 20:22:19

标签: ruby regex

我有两种类型的字符串。如果字符串首先包含foo bar bar,则不应触及该字符串。如果它仅包含bar,则qux应替换为"sometext foo someothetext bar somethirdtext"

  • "sometext bar someothetext"不应该被触及
  • "sometext qux someothetext" =&gt; str.gsub! (/(?<!foo)(.*)bar/), '\1qux'

看起来我需要使用负面外观,但我无法让它正常工作。目前,我有一个表达:

bar

但是,它会在两个字符串中将qux替换为.*。我有一种感觉{{1}}搞砸了。我无法找到背后的示例,其中群组后面的内容不会立即出现在匹配群组之前。

3 个答案:

答案 0 :(得分:0)

如果你可以使用可变长度的lookbehinds,你可以将/(?<!foo.*)bar/的匹配替换为'qux'

如果不支持可变长度的lookbehinds,你可以真正使用lookbehind因为你无法知道启动lookbehind以查找foo的位置。以下是如何通过前瞻来做到这一点:

str.gsub!  (/\A(((?!foo).)*)bar/m), '\1qux'

说明:

\A           # match at the start of the string
(            # start capture group 1
  (            # start capture group 2, repeat 0 or more times
    (?!foo)      # fail if 'foo' can match here
    .            # match a single character
  )*           # end capture group 2
)            # end capture group 1
bar          # match 'bar'

这会对每个字符执行否定前瞻(?!foo),直到我们匹配bar,因此它不会匹配foo之前bar所在的字符串。

到字符串开头的锚是必要的,因为如果你可以从字符串的中间开始,它将在f foo之后立即开始匹配。使用多行选项,以便.字符匹配换行符,不确定这是否对您正在进行的操作是必要的。

答案 1 :(得分:0)

您可以执行以下操作:

if str.include? "foo"
  str = str.slice(0, str.index("foo")-1).sub("bar","qux") + str.slice(str.index("foo")-1, str.length)
else
  str = str.sub("bar","qux")
end

它将在“foo”的第一个实例之前替换任何“bar”,然后在其余的字符串上添加

答案 2 :(得分:0)

也许您可以使用flag来跟踪前面是否有foo

flag = false
"sometext foo someothetext bar somethirdtext"
.gsub(/(foo)|bar/){flag = true if $1; flag ? $& : "qux"}
# => "sometext foo someothetext bar somethirdtext"

flag = false
"sometext bar someothetext"
.gsub(/(foo)|bar/){flag = true if $1; flag ? $& : "qux"}
# => "sometext qux someothetext"