argsと「終了しない引用文字列」/「予期しないEOF」から読み取ったコマンドを使用してsh(ダッシュ)からbashを呼び出す

argsと「終了しない引用文字列」/「予期しないEOF」から読み取ったコマンドを使用してsh(ダッシュ)からbashを呼び出す

記録を修正したかったです。私は非常に簡単な作業を試しています。環境変数を設定してbash印刷します。

$ bash -c "a=1; echo a$a;"
a
$ bash -c "a=1; echo a\$a;"
a1

今私は同じことをしたいがsh(私のシステムでls -la $(which sh)与えられた/bin/sh -> dash)というパラメータを使用します。

$ sh -c "bash -c "a=1; echo a\$a;""
a$a

# obviously I have to escape inner quotes:

$ sh -c "bash -c \"a=1; echo a\$a;\""
a

# escape the dollar once more?

$ sh -c "bash -c \"a=1; echo a\\$a\" "
sh: Syntax error: Unterminated quoted string

# nope... inner single quotes, then?

$ sh -c "bash -c 'a=1; echo a$a;'"
a

# nope... escape the single quotes?

$ sh -c "bash -c \'a=1; echo a$a;\'"
bash: -c: line 0: unexpected EOF while looking for matching `''
bash: -c: line 1: syntax error: unexpected end of file
a
sh: ': not found

# nope... escape the dollar too?

$ sh -c "bash -c \'a=1; echo a\$a;\'"
bash: -c: line 0: unexpected EOF while looking for matching `''
bash: -c: line 1: syntax error: unexpected end of file
a
sh: ': not found

sh -c [bash -c ...]だから私の質問は - 今のような結果を得るためにエスケープする正しい構文は何ですかbash -c ...

答え1

一重引用符の中には特別な意味を持つ文字はありません。二重引用符の中には"\$`特別な意味があります。外側から内側への作業:まず、外側のシェルがどのストラップで作られているかを特定し、次に内側のシェルがどのストラップで作られているかを確認します。

たとえば、変数がaシェルで定義されていないとします。

sh -c "bash -c \"a=1; echo a\$a;\""

シェルは二重引用符で囲まれた文字列を表示して展開し、bash -c "a=1; echo a$a;"その文字列は途中で渡されますsh。これをsh2つの引数を持つ呼び出しに解析し、後者は未定義変数の二重引用符で囲まれた文字列を拡張した結果です。bash-ca=1; echo a;"a=1; echo a$a;"a

この分析は、あなたが望むものを得るための1つの方法が"a=1; echo a\$a;"この段階で得られることです。この追加のバックスラッシュを取得するには、二重引用符内にすでにシェル拡張ステップがあるため、元のファイルに2つのバックスラッシュを追加する必要があります。 2 プラス 1 は 3 と同じです。

sh -c "bash -c \"a=1; echo a\\\$a;\""

外側の文字列に一重引用符を使用する方が簡単です。その中のどんなものも拡張したくないからです。

sh -c 'bash -c "a=1; echo a\$a;"'

bashどちらにでも呼び出すときに何も拡張したくないので、shここでは一重引用符を使用することもできます。一重引用符で囲まれた文字列の中に一重引用符を入れることはできませんが、これをシミュレートする方法があります。 put '\''。正式には、一重引用符リテラルを終了し、一重引用符リテラルを追加し、新しい一重引用符リテラルを開始しますが、4文字のシーケンスを一重引用符で囲まれた文字列に'\''一重引用符を入れる方法と考えることができます。

sh -c 'bash -c '\''a=1; echo a$a;'\'''

最後に省略してもかまいません''。それほど体系的ではありませんが、見やすいです。

sh -c 'bash -c '\''a=1; echo a$a;'\'

一重引用符は二重引用符の中にある特別なものではないため、シェルの拡張を"bash -c 'a=1; echo a\$a;'"防ぐには、書くときにドルの前にバックスラッシュを付ける必要があります。$a

答え2

まあ、私はうまくいきました(ちょうどこれはUbuntu 11.04です):

$ sh -c "bash -c 'a=1; echo a\$a \'"
a1
$ sh -c "bash -c 'a=1; echo a\$a;'"
a1

...最初の一重引用符がエスケープされておらず、ドルもエスケープされている限り、最後の一重引用符がエスケープされたかどうかに関係なく動作するようです!まだ混乱しています...

関連情報