10
s = "#main= 'quotes'
s.gsub "'", "\\'" # => "#main= quotes'quotes"

これは間違っているようです、私は得ることを期待しています"#main= \\'quotes\\'"

エスケープ文字を使用しない場合は、期待どおりに機能します。

s.gsub "'", "*" # => "#main= *quotes*"

ですから、逃げることと関係があるに違いありません。

ルビー1.9.2p290の使用

一重引用符を円記号と引用符に置き換える必要があります。

さらに多くの矛盾:

"\\'".length # => 2
"\\*".length # => 2

# As expected
"'".gsub("'", "\\*").length # => 2
"'a'".gsub("'", "\\*") # => "\\*a\\*" (length==5)

# WTF next:
"'".gsub("'", "\\'").length # => 0

# Doubling the content?
"'a'".gsub("'", "\\'") # => "a'a" (length==3)

ここで何が起こっているのですか?

4

3 に答える 3

19

\'正規表現置換文字列内の特殊性につまずきます:

\0、、、...\1\2\9\&\`\'\+
、、、、、 n番目のグループ化された部分式、または一致全体、一致前または一致後、または最も高いグループによって一致した置き換えます

つまり、と言う"\\'"と、double\\は1つの円記号になり、結果は\'「最後に成功した一致の右側の文字列」を意味します。一重引用符をエスケープされた一重引用符に置き換えたい場合は、次の特殊性を乗り越えるためにさらにエスケープする必要があります\'

s.gsub("'", "\\\\'")

または、つまようじを避けて、ブロックフォームを使用します。

s.gsub("'") { |m| '\\' + m }

バックティック、プラス記号、または1桁の数字をエスケープしようとすると、同様の問題が発生します。

ここでの全体的な教訓は、最も些細な置換以外のすべてのブロック形式を優先することです。gsub

于 2011-08-16T07:13:20.623 に答える
3
s = "#main = 'quotes'

s.gsub "'", "\\\\'"

二重のバックスラッシュを取得したい場合は同等であるため、1 を 4 つ入れる必要があり\ます。\\

于 2011-08-16T06:36:16.410 に答える
2

\ もエスケープする必要があります。

s.gsub "'", "\\\\'"

出力

"#main= \\'quotes\\'"

外部フォーラムで見つけた良い説明:

私見を理解するための重要なポイントは、バックスラッシュが置換文字列で特別であることです。したがって、置換文字列にリテラルのバックスラッシュが必要なときはいつでも、それをエスケープする必要があるため、[2] 個のバックスラッシュが必要です。偶然にも、文字列内のバックスラッシュも特殊です (一重引用符で囲まれた文字列内であっても)。したがって、2 レベルのエスケープが必要であり、画面上で 2 * 2 = 4 つのバックスラッシュを 1 つのリテラル置換バックスラッシュにします。

ソース

于 2011-08-16T06:36:37.527 に答える