次のような文字列があります。
abcab " ab " ba " a "
a
で区切られた文字列の一部ではないすべてに一致させるにはどうすればよい"
ですか? ここで太字になっているものすべてに一致させたい:
a bc a b " ab " b a " a "
これらの一致を置き換えたい (または空の文字列に置き換えて削除したい) ため、引用符で囲まれた部分を削除して一致させることはできません。それらを文字列に残しておきたいからです。ルビーを使用しています。
引用符が正しくバランスが取れていて、引用符がエスケープされていないと仮定すると、簡単です。
result = subject.gsub(/a(?=(?:[^"]*"[^"]*")*[^"]*\Z)/, '')
a
これは、一致した の前に偶数個の引用符がある場合にのみ、すべての を空の文字列に置き換えますa
。
説明:
a # Match a
(?= # only if it's followed by...
(?: # ...the following:
[^"]*" # any number of non-quotes, followed by one quote
[^"]*" # the same again, ensuring an even number
)* # any number of times (0, 2, 4 etc. quotes)
[^"]* # followed by only non-quotes until
\Z # the end of the string.
) # End of lookahead assertion
引用符 ( ) 内で引用符をエスケープできる場合a "length: 2\""
でも可能ですが、より複雑になります。
result = subject.gsub(/a(?=(?:(?:\\.|[^"\\])*"(?:\\.|[^"\\])*")*(?:\\.|[^"\\])*\Z)/, '')
これは本質的に上記と同じ正規表現であり、次の部分のみを置き換え(?:\\.|[^"\\])
てい[^"]
ます。
(?: # Match either...
\\. # an escaped character
| # or
[^"\\] # any character except backslash or quote
) # End of alternation
js-coder は、言及されていない単純な解決策を持っていたため、この古い質問を復活させました。(正規表現バウンティクエストの調査中にあなたの質問を見つけました。)
ご覧のとおり、受け入れられた回答の正規表現と比較して、正規表現は非常に小さいです。("[^"]*")|a
subject = 'a b c a b " a b " b a " a "'
regex = /("[^"]*")|a/
replaced = subject.gsub(regex) {|m|$1}
puts replaced
このライブデモを見る
参照
パフォーマンスやコードの読みやすさを気にすることなく、正規表現愛好家のための本格的な正規表現ソリューション。
このソリューションでは、エスケープ構文がないことを前提としています (エスケープ構文では、a
in"sbd\"a"
は文字列の内側としてカウントされます)。
擬似コード:
processedString =
inputString.replaceAll("\\".*?\\"","") // Remove all quoted strings
.replaceFirst("\\".*", "") // Consider text after lonely quote as inside quote
次に、必要なテキストを に一致させることができますprocessedString
。単独引用符の後のテキストを外部引用符と見なす場合は、2 番目の置換を削除できます。
編集
Ruby では、上記のコードの正規表現は次のようになります。
/\".*?\"/
で使用gsub
と
/\".*/
で使用sub
交換の問題に対処するために、これが可能かどうかはわかりませんが、試してみる価値はあります:
/(\"|a)/
gsub で正規表現を使用し、関数を提供します。"
、 counter をインクリメント"
し、置換として返します (基本的には変更なし)。一致する場合はa
、カウンターが偶数かどうかを確認します。置換文字列を指定した場合。それ以外の場合は、一致するものは何でも提供してください。