web-dev-qa-db-ja.com

sedで二重引用符と単一引用符をエスケープするにはどうすればよいですか?

私が見つけることができることから、単一引用符を使用すると、内部のすべてがリテラルと見なされます。私の代わりにそれが欲しい。しかし、一重引用符または二重引用符を含む文字列も見つけたいです。

例えば、

sed -i 's/"http://www.fubar.com"/URL_FUBAR/g'

「http://www.fubar.com」をURL_FUBARに置き換えたい。 sedはどのようにして//または二重引用符を認識するのですか?

助けてくれてありがとう!

編集:s/\"http\:\/\/www\.fubar\.\com\"/URL_FUBAR/gを使用できますか?

\は実際に単一引用符内の文字をエスケープしますか?

63
KRB

sedコマンドを使用すると、sコマンドの区切り文字として/の代わりに他の文字を使用できます。

sed 's#"http://www\.fubar\.com"#URL_FUBAR#g'

または

sed 's,"http://www\.fubar\.com",URL_FUBAR,g'

二重引用符は問題ではありません。単一引用符を一致させるには、2種類の引用符を切り替えます。単一引用符で囲まれた文字列には、単一引用符が含まれない場合があります(エスケープされたものでさえも)。

sedがドットを解釈し、任意の1文字と一致する正規表現パターン.としてではない場合、ドットをエスケープする必要があります。

84
Kusalananda

単一引用符については、文字列let'slet usに置き換えるために使用される以下のコードを参照してください。

コマンド:

echo "hello, let's go"|sed 's/let'"'"'s/let us/g'

結果:

こんにちは、行かせて

25
tony duan

単一引用符内の単一引用符をエスケープすることは困難です。これを試して:

sed "s@['\"]http://www.\([^.]\+).com['\"]@URL_\U\1@g" 

例:

$ sed "s@['\"]http://www.\([^.]\+\).com['\"]@URL_\U\1@g" <<END
this is "http://www.fubar.com" and 'http://www.example.com' here
END

生産する

this is URL_FUBAR and URL_EXAMPLE here
12
glenn jackman

私の問題は、sed式自体の内部に動的変数があるため、式の外側に""が必要だということでした。したがって、実際の解決策は、lenジャックマンからのもので、sed正規表現内の"[\"]に置き換えることです。

だから私の完全なbashは:

RELEASE_VERSION="0.6.6"

sed -i -e "s#value=[\"]trunk[\"]#value=\"tags/$RELEASE_VERSION\"#g" myfile.xml

ここは:

#はsedセパレーターです

[\"] = "正規表現で

値= \"tags/$RELEASE_VERSION\" =置換文字列、重要なのは引用符用の\"だけである

9
Denis

二重引用符のエスケープは、sedでは絶対に必要です。たとえば、sed式全体で二重引用符を使用している場合(シェル変数を使用するときに行う必要があります)。

以下は、sedでのエスケープについて触れた例ですが、bashでの引用に関する他の問題もいくつか示しています。

# cat inventory
PURCHASED="2014-09-01"
SITE="Atlanta"
LOCATION="Room 154"

繰り返し使用できるsedスクリプトを使用して部屋を変更したい場合、次のように入力を可変化します。

# i="Room 101" (these quotes are there so the variable can contains spaces)

このスクリプトは、行がない場合は行全体を追加するか、(sedを使用して)行にテキストと$ iの値を単に置き換えます。

if grep -q LOCATION inventory; then 
## The sed expression is double quoted to allow for variable expansion; 
## the literal quotes are both escaped with \ 
    sed -i "/^LOCATION/c\LOCATION=\"$i\"" inventory
## Note the three layers of quotes to get echo to expand the variable
## AND insert the literal quotes
else 
    echo LOCATION='"'$i'"' >> inventory
fi

追伸コメントを解析可能にするために、上記のスクリプトを複数行に分けて書きましたが、次のようなコマンドラインのワンライナーとして使用します。

i="your location"; if grep -q LOCATION inventory; then sed -i "/^LOCATION/c\LOCATION=\"$i\"" inventory; else echo LOCATION='"'$i'"' >> inventory; fi

余談:変数を正しく解釈するには、BASH変数を含むsed式を二重(")で囲む必要があります。

also$ BASH変数を二重引用符で囲む場合(推奨される方法)

...次に示すように、変数の二重引用符をエスケープできます。

sed -i "s/foo/bar ""$VARIABLE""/g" <file>

つまり、$ VARIABLEに関連付けられた"""に置き換えます。

(単に、"$VAR"\"$VAR\"としてエスケープすると、"で囲まれた出力文字列になります。)


$ VAR='apples and bananas'
$ echo $VAR
apples and bananas

$ echo "$VAR"
apples and bananas

$ printf 'I like %s!\n' $VAR
I like apples!
I like and!
I like bananas!

$ printf 'I like %s!\n' "$VAR"
I like apples and bananas!

ここで、$ VARはsedにパイピングする前に"- quoted(sedは'-または"- quoted)です:

$ printf 'I like %s!\n' "$VAR" | sed 's/$VAR/cherries/g'
I like apples and bananas!

$ printf 'I like %s!\n' "$VAR" | sed 's/"$VAR"/cherries/g'
I like apples and bananas!

$ printf 'I like %s!\n' "$VAR" | sed 's/$VAR/cherries/g'
I like apples and bananas!

$ printf 'I like %s!\n' "$VAR" | sed 's/""$VAR""/cherries/g'
I like apples and bananas!

$ printf 'I like %s!\n' "$VAR" | sed "s/$VAR/cherries/g"
I like cherries!

$ printf 'I like %s!\n' "$VAR" | sed "s/""$VAR""/cherries/g"
I like cherries!

それと比較してください:

$ printf 'I like %s!\n' $VAR | sed "s/$VAR/cherries/g"
I like apples!
I like and!
I like bananas!


$ printf 'I like %s!\n' $VAR | sed "s/""$VAR""/cherries/g"
I like apples!
I like and!
I like bananas!

... 等々 ...

結論

標準的な慣行としての私の推奨事項は

  • "- quote BASH変数("$VAR"
  • "- quote、again、sed式で使用される変数(""$VAR"")(それ自体は"-でなければなりません) '- quotedではなく、引用符で囲まれています)
$ VAR='apples and bananas'

$ echo "$VAR"
apples and bananas

$ printf 'I like %s!\n' "$VAR" | sed "s/""$VAR""/cherries/g"
I like cherries!

0
Victoria Stuart
Prompt% cat t1
This is "Unix"
This is "Unix sed"
Prompt% sed -i 's/\"Unix\"/\"Linux\"/g' t1
Prompt% sed -i 's/\"Unix sed\"/\"Linux SED\"/g' t1
Prompt% cat t1
This is "Linux"
This is "Linux SED"
Prompt%
0
SachinH