web-dev-qa-db-ja.com

sedでスラッシュとバックスラッシュの両方をエスケープする

次の文字列があります:/tmp/test/folder1/test.txt

sedを代わりに使用したい/ ために \/ - 例えば:

\/tmp\/test\/folder1\/test.txt

だから私は発行します:

echo "/tmp/test/folder1/test.txt" | sed "s/\//\\\\//g"

それは返しますが:

sed:-e expression#1、char 9: `s 'のオプションが不明

スラッシュとバックスラッシュをエスケープしています-ここでどこが間違っているのかわかりません

9
James

すべての置換されたスラッシュ\とすべてのバックスラッシュ/を(バックスラッシュ\で)エスケープする必要があるため、次のようにします。

$ echo "/tmp/test/folder1/test.txt" | sed 's/\//\\\//g'
\/tmp\/test\/folder1\/test.txt

しかし、それはかなり判読できません。

ただし、sedでは、ほとんどすべての文字を/の代わりに区切り文字として使用できます。これは、ケースのようにスラッシュ/自体を置き換える場合に特に便利です。セミコロン;の例として、区切り文字としてコマンドを使用すると簡単になります。

echo "/tmp/test/folder1/test.txt" | sed 's;/;\\/;g'

その他の場合:

  • 区切り文字としてスラッシュを使用し、二重引用符を使用する場合は、エスケープされたすべてのバックスラッシュをもう一度エスケープして、リテラル値を保持する必要があります。

    echo "/tmp/test/folder1/test.txt" | sed "s/\//\\\\\//g"
    
  • 引用符がまったく必要ない場合は、さらに別のバックスラッシュが必要です。

    echo "/tmp/test/folder1/test.txt" | sed s/\\//\\\\\\//g
    
23
jimmij

または、値が(bash)シェル変数にある場合:

var=/tmp/test/folder1/test.txt
$ echo "${var//\//\\\/}"
\/tmp\/test\/folder1\/test.txt

最初 // start パラメータ展開allを置き換えると一致すると置換に一致します。次の\/はエスケープされた/と一致し、\\\/はエスケープされた\の後にエスケープされた/の代わりとして。

6
Jeff Schaller

最終的な解決策はこれです:

$ sed 's:/:\\/:g'  <<<"$str"
\/tmp\/test\/folder1\/test.txt

しかし、そこに着く方法を説明するには:
はい、1つのバックスラッシュがありませんでした:

$ str='/tmp/test/folder1/test.txt'
$ sed "s/\//\\\\\//g" <<<"$str"
\/tmp\/test\/folder1\/test.txt

1つのスペースでそれが明確になることを願っています。

$ sed "s/\//\\\\ \//g"  <<<"$str"
\ /tmp\ /test\ /folder1\ /test.txt

ただし、sed区切り文字を:に変更する場合(例):

$  sed "s:\/:\\\\\/:g"  <<<"$str"
\/tmp\/test\/folder1\/test.txt

ただし、(現在は特別ではありません)/はスキャッピングする必要がないため、これは厳密には正しくありません。

$ sed "s:/:\\\\/:g"  <<<"$str"
\/tmp\/test\/folder1\/test.txt

また、二重引用符の代わりに単一引用符を使用する場合、シェルは二重\\を1に変更しないため、少ない\が正しいでしょう。

$ sed 's:/:\\/:g'  <<<"$str"
\/tmp\/test\/folder1\/test.txt

かなりきれいです。

2
Isaac