web-dev-qa-db-ja.com

二重引用符のエスケープは避けてください

Bashスクリプトで実行したいコマンドがいくつかあります。
一重引用符を使用すると、変数は値ではなくリテラルとして使用されるようになりました。
そうすることで、例えばls "$SOME_DIR"ls '$SOME_DIR'と同じではありません
二重引用符をエスケープすることですべてが乱雑にならないように、引用符と二重引用符の組み合わせを処理するにはどうすればよいですか?
例えば。次のようなものを有効にする方法:

ssh server.com "mkdir \"/foo/bar/"$final"\""  

コマンドが長くなると判読できなくなり、非常に簡単に壊れてしまうため、これらすべてのエスケープを回避するにはどうすればよいですか?

2
Jim

heredocsherestringsを何度も試した後、最も簡単な解決策は次のようになります。

ssh server.com "mkdir '/foo/bar/$final'"

はい、bashは、$finalの場合と同様に、一重引用符にもかかわらず、echo "test'$final'"の変数置換を行います。

注:@muruが指摘しているように、$finalに一重引用符が含まれている場合は機能しません。

3
Rastapopoulos

反対の引用符(つまり二重引用符で囲まれた一重引用符、およびその逆)は、エスケープの代わりに使用できます。エスケープまたはヒアドキュメントを使用せずに、echoを使用してこのテキストを表示する方法を検討してください。

彼は振り返らず、「仕方がない」と言った。

二重引用符または一重引用符で囲むことはできません。反対の引用符を交互に使用すると機能します。

echo "He didn't look back, and said "'"It can'"'t be helped."'"'

出力:

He didn't look back, and said "It can't be helped."

残念ながら、上記のechoは、エスケープと同じように読むのが困難です。

幸せな媒体は、視覚的な単調さを減らすために、必要に応じて反対の引用符とエスケープの両方を使用することです。

echo "He didn't look back, and said \"It can't be helped.\""

コードに適用:

ssh server.com 'mkdir "'"/foo/bar/$final"\"

これは、$final'が含まれている場合でも機能するはずです。

見積もりを展開すると、次のようになります。

  1. 'mkdir "'、スペースと開始二重引用符を保持します。
  2. sshを起動する前に"/foo/bar/$final"の内容を返す$final
  3. \"二重引用符を閉じ、sshのdirnameを保持します
1
agc

実際に必要なのは、変数を展開する場所とタイミング(ローカルでコマンドを送信する前、またはリモートで送信した後)に大きく依存すると思います。どちらの場合も有効です。いずれにせよ、コマンドが1行に収まる場合は、コマンドを囲む<<<リダイレクトをそれぞれ二重引用符または一重引用符で使用することをお勧めします。

1。コマンドを送信する前に変数を解決する

final="defined_locally"; ssh server.com <<<"final="defined_remotely" ;mkdir /foo/bar/"$final" "

2。コマンド送信後の変数の解決

final="defined_locally"; ssh server.com <<<'final="defined_remotely"; mkdir /foo/bar/"$final" '

最初のものが作成されます

/ foo/bar/defined_locally

そして2番目のものが作成されます

/ foo/bar/defined_remotely

リモートサーバー上のディレクトリ

ご覧のとおり、1つのコマンドでローカルとリモートで定義された変数を混在させるまで、どちらの場合もエスケープする必要はありません。

UPD:

<<<

厳密に言えば、リダイレクトではありませんが、 HERE-STRING

UPD2:

を指し示してくれた@Rastapopoulosに感謝します

コマンドの実行に伴うPseudo-terminal will not be allocated because stdin is not a terminalメッセージ

害はありませんが

0
Tagwint

これはprintfビルトインの仕事ですか?

ldo@theon:~> f='He didn'\''t look back, and said "It can'\''t be helped."'
ldo@theon:~> echo "$f"
He didn't look back, and said "It can't be helped."
ldo@theon:~> ssh hypatia echo "$f"
bash: -c: line 0: unexpected EOF while looking for matching `"'
bash: -c: line 1: syntax error: unexpected end of file
ldo@theon:~> ssh hypatia echo $(printf %q "$f")
He didn't look back, and said "It can't be helped."
0