3

2種類の弦を持っています。文字列にfoofirst と laterが含まれている場合はbar、触れないでください。のみが含まれている場合barは、barを に置き換える必要がありますqux

  • "sometext foo someothetext bar somethirdtext"触れてはいけない
  • "sometext bar someothetext"=>"sometext qux someothetext"

ネガティブルックビハインドを使用する必要があるようですが、正しく機能させることができません。現在、私は式を持っています:

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

ただし、両方の文字列でbartoに置き換えられます。私は物事を台無しquxにする感じがあります。.*後読みグループが一致したグループにすぐに先行しない後読みの例を見つけることができませんでした。

4

3 に答える 3

0

可変長の後読みを使用できる場合は、一致する を に置き換えるだけ/(?<!foo.*)bar/です'qux'

可変長後読みがサポートされていない場合は、後読みを開始する位置がわからないため、後読みを実際に使用できます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ある文字列には一致しません。foobar

f文字列の途中から開始できる場合、 inの直後に一致が開始されるため、文字列の先頭へのアンカーが必要ですfoo。文字が改行に一致するように複数行オプションが使用されますが.、これがあなたがしていることに必要かどうかはわかりません。

于 2013-01-08T20:30:21.897 に答える
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」を置き換えてから、残りの文字列を追加します

于 2013-01-08T20:38:24.877 に答える
0

おそらく、 aを使用して、先行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"
于 2013-01-08T22:33:05.293 に答える