質問

ました、こんにRubyのコード:

>> puts '\\ <- single backslash'
# \ <- single backslash

>> puts '\\ <- 2x a, because 2 backslashes get replaced'.sub(/\\/, 'aa')
# aa <- 2x a, because two backslashes get replaced

これまでに、すべてのとして期待される。その検索1 /\\/, たり、不具合を放置した場合、その2つの符号化された '\\\\', で、なぜいます:

>> puts '\\ <- only 1 ... replace 1 with 2'.sub(/\\/, '\\\\')
# \ <- only 1 backslash, even though we replace 1 with 2

そして、エンコード3 '\\\\\\', してのみ2:

>> puts '\\ <- only 2 ... 1 with 3'.sub(/\\/, '\\\\\\')
# \\ <- 2 backslashes, even though we replace 1 with 3

誰でも理解できるのはなぜバックスラッシュが飲み込んだの置換文字列?この関1.8および1.9.

役に立ちましたか?

解決

バックスラッシュ(\)は正規表現と文字列のエスケープ文字として機能しますので、

これが問題です。あなたは特別な変数を使用\&GSUBの置換文字列に番号のバックスラッシュを減らすために行うことができます。

foo.gsub(/\\/,'\&\&\&') #for some string foo replace each \ with \\\

編集:私は、\&の値が、この場合、単一のバックスラッシュには、正規表現のマッチからのものであることを言及する必要があります。

また、私は、エスケープ文字を無効にして、文字列を作成するための特別な方法があったと思ったが、どうやらありません。これらはいずれも2つのスラッシュを生成しません。

puts "\\"
puts '\\'
puts %q{\\}
puts %Q{\\}
puts """\\"""
puts '''\\'''
puts <<EOF
\\
EOF  

他のヒント

迅速に回答

したい場合に訪れているすべてこの混乱の中、 利用にかくブロックの書式.ここでは例と置き換えバックスラッシュと2つのバックスラッシュ:

"some\\path".gsub('\\') { '\\\\' }

身の毛もよだつよう内容

問題は、その利用の場合 subgsubなしに、ブロックとして、rubyの解釈 特殊文字の配列 差し替えでパラメータとします。残念ながら、 sub のバックスラッシュとしてエスケープ文字はこれら:

\& (the entire regex)
\+ (the last group)
\` (pre-match string)
\' (post-match string)
\0 (same as \&)
\1 (first captured group)
\2 (second captured group)
\\ (a backslash)

というの脱出、明らかな問題です。したい場合は、リテラル値の配列(例: \1 の出力文字列で逃がします。では、さっそく Hello \1, が必要になり交換する文字列 Hello \\1.を表す文字列リテラルとしてRuby、逃げの方にバックスラッシュを再びこのように: "Hello \\\\1"

が分かります 異なる二つの脱出経過.最初の文字列リテラルを作成し、内部文字列になる。第二はこの内部文字列値に置き換え配列上にマッチングデータです。

の場合バックスラッシュはその後の文字に一致する上記の配列をバックスラッシュ(および文字ることはありませんが,下記の通りわ.このものにも影響を与えるバックスラッシュの末尾に文字列でじわ.でも簡単にこの論理のrubiniusコードただ一つの to_sub_replacement 方法の Stringクラス.

ここでは 一例 どのよう String#sub が構文解析の置換文字列:

  • 1バックスラッシュ \ (文字列リテラルの "\\")

    通己責任でバックスラッシュは文字列の末尾にくいから後ろの文字です。

    結果: \

  • 2バックスラッシュ \\ (あるいは文字列リテラルの "\\\\")

    一対のバックスラッシュの試合では、逃バックスラッシュ配列参照 \\ とくに換算し単一のバックスラッシュ.

    結果: \

  • 3バックスラッシュ \\\ (あるいは文字列リテラルの "\\\\\\")

    最初の二つのバックスラッシュに合わせ \\ 配列変換される単一のバックスラッシュ.そして最後のバックスラッシュは文字列の末尾にも通過することにより、わ.

    結果: \\

  • 4バックスラッシュ \\\\ (あるいは文字列リテラルの "\\\\\\\\")

    二つのペアのバックスラッシュ試合の \\ 配列変換される単一のバックスラッシュ.

    結果: \\

  • 2バックスラッシュ文字は、文字中 \a\ (あるいは文字列リテラルの "\\a\\")

    \a 致しないのは、エスケープシーケンスで過わ.最後のバックスラッシュも可能です。

    結果: \a\

    注意: 同じ結果が得られることから: \\a\\ (リテラル文字列: "\\\\a\\\\")

後から振り返ってみると、これが内外ともに下落幅が縮小していく場合 String#sub した異なるエスケープ文字です。それはないと思いますのdoubleを逃すべてのバックスラッシュ.

なんてこった、私はこのすべてを入力した直後、私は\は、置換文字列内のグループを参照するために使用されていることに気づきました。私は、これはあなたが1置き換え\\を取得するには、置換文字列リテラル\が必要であることを意味を推測します。あなたがそうあなたが実際に8を必要とする2のものを置き換えるために、4 \\sを必要とするリテラル\を取得するには(!)。

# Double every occurrence of \. There's eight backslashes on the right there!
>> puts '\\'.sub(/\\/, '\\\\\\\\')

何も私が欠けていますか?任意のより効率的な方法?

コードの作者の2行目に少し混乱をクリアます。

あなたは言います:

>> puts '\\ <- 2x a, because 2 backslashes get replaced'.sub(/\\/, 'aa')
# aa <- 2x a, because two backslashes get replaced

2のバックスラッシュは、ここでは置き換え取得されていません。あなたが交換しているの 1は、2つの( 'AA')でのバックスラッシュをエスケープ。つまり、あなたが.sub(/\\/, 'a')を使用した場合、あなたは唯一の「A」を見るでしょう。

'\\'.sub(/\\/, 'anything') #=> anything

つるはしの本は実際に、この正確な問題に言及しています。ここで(最新版の130ページから)別の代替だ。

str = 'a\b\c'               # => "a\b\c"
str.gsub(/\\/) { '\\\\' }   # => "a\\b\\c"
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top