web-dev-qa-db-ja.com

sh-cのシェルエスケープ文字

Sh -cを使用して、エスケープされた引数を使用してコマンドを実行する必要があります。文字列がかなり醜いように見えることは知っていますが、単純な文字列は問題を引き起こしません。

Sh -cに渡されたときのエコーの出力は、スタンドアロンで実行されたときとは異なり、修正方法を見つけるのに苦労しています。

背景:[1]これが渡され、余分なコマンドが挿入されていないことを確認したかったので、echoコマンドの引数をエスケープしています。 [2] |のようなシェル機能を使用できるようにしたかったので、sh-cを使用しています。またはNohupなど。[3]おそらく関係ありませんが、これはリモートサーバーへのssh接続を介して実行されています。

Sh-cコマンドのコマンドと出力は次のとおりです。

sh -c "echo \a\\\\\b\;\c"

;c

スタンドアロンコマンドのコマンドと出力は次のとおりです。

echo \a\\\\\b\;\c

a\\b;c

どんな助けでも大歓迎です!

2
Stuart

\は、いくつかの文字(\自体、"$`など)をエスケープし、二重引用符で囲まれた改行文字を削除するために使用されます。

sh -c "echo \a\\\\\b\;\c"

のようなものです

sh -c 'echo \a\\\b\;\c'

そのshの場合、\はすべての文字をエスケープするために使用されるため、次のようになります。

echo 'a\b;c'

UNIX準拠のechosは、\bをバックスペース文字(^H)に展開します。これは、端末に送信されると、カーソルを1文字左に移動するため、;は上書きされます。 a、これが;cが表示される理由です。

echoは移植性のないコマンドであり、その動作はシェルごと、システムごとに大きく異なります。特に、円記号を含む場合やダッシュで始まる場合がある引数を指定する場合は、避けるのが最善です。代わりにprintfを使用してください。

sh -c 'printf "%s\n" "a\\\\b;c"'

a\\b;cを出力します。

(3つの円記号で十分でしたが、二重引用符で囲む場合、1つを取得するには2つの円記号が必要であることを覚えておく方が安全です)。

あなたのようなエスケープシーケンスを拡張するecho実装の場合、バックスラッシュの数を2倍にする必要があります。

sh -c 'echo "a\\\\\\\\b;c"'

二重引用符を避けたい場合は、シェルに特別な唯一の;文字をエスケープするだけで済みます(すでに二重引用符でエスケープした\に加えて) -見積もりバージョン)。

sh -c 'echo a\\\\\\\\b\;c'

一重引用符の代わりに二重引用符を使用する場合は、バックスラッシュの数を2倍にする必要があります。

sh -c "echo a\\\\\\\\\\\\\\\\b\\;c"

また、引用符を削除したい場合は、スペースをエスケープして、外側のシェル用にもう一度;する必要があります。

sh -c echo\ a\\\\\\\\\\\\\\\\b\\\;c
2