2017-01-17 5 views
2

引用符とパイプをエスケープする方法は?引用符とパイプをbash文字列でエスケープする

#!/bin/bash 
set -x 
MYCMD="VBoxManage showvminfo --machinereadable $1 \| grep \'VMState=\"poweroff\"\'" 
echo "`$MYCMD`" 

実行されたコマンド:

++ VBoxManage showvminfo --machinereadable d667 '|' grep '\'\''VMState="poweroff"\'\''' 

そして最後に、このエラーを取得:

Syntax error: Invalid parameter '|' 
+0

(バッククォートを使用して)コマンドの出力をキャプチャしてから、エコーすることは反パターンです。コマンドを直接実行して、出力を通常の場所に移動させてください。ところで、もっと直接的に実行するのではなく、変数にコマンドを格納する実際の理由は何ですか? –

答えて

7

あなたはしないでください。通常の文字列パラメータに任意のパイプラインを埋め込むには、evalを使用する必要があります。あなたが$1の値が問題を引き起こすことはありません特定ない限り

MYCMD="VBoxManage showvminfo --machinereadable \"$1\" | grep 'VMState=\"poweroff\"'" 
eval "$MYCMD" 

ただし、これは推奨されません。 (あなたはこれらのリスクは、その後、あなたがevalを使用すべきではないかもしれないものの説明が必要な場合。)その代わり

、シェル関数を定義します。それを行うには

mycmd() { 
    VBoxManage showvminfo --machinereadable "$1" | grep 'VMState="poweroff"' 
} 

mycmd "$1" 
+0

シェル関数がこの問題を解決しました。 Chepnerありがとう! – Jonas

0

一つの本当に簡単な方法は、使用しています配列または位置パラメータ

アレイベースのソリューション:

# Build command 
declare -a CMD_AND_ARGS=(command and args with normal quoting) 

# Append arguments 
CMD_AND_ARGS+=(more arguments quoted the normal way) 

# Execute command 
"${CMD_AND_ARGS[@]}" 

位置パラメータベースのソリューション:

# Create command 
set -- command and args with normal quoting 

# Append arguments 
set -- "[email protected]" more arguments quoted the normal way 

# Execute command 
"[email protected]" 

両方のソリューションのいいところは、位置パラメータを展開するので、あなたは、引用符内の引用符を配置する必要はありませんですまたは二重引用符で囲まれた配列は、単語分割と展開を再度実行しません。

例:両方のケースでは、あなたのスクリプトの流れに応じて、異なる引数を追加する(例:IF /ケース)を選択するインスタンス持つ条件式のため、インクリメンタルあなたのコマンドを構築するために取得すること

declare -a CMD=() 
CMD=(ls "/dir/with spaces/in its name") 
"$CMD" 

set -- ls "/dir/with spaces/in its name" 
"[email protected]" 

注意。

コマンドを別のパイプにパイプしたい場合は、|のシンボルを引用符で囲まれていない配列宣言内で使用することはできないため、各コマンドを別々に構築する必要があります(たとえば2つの配列)配管が行われることはありません。

+1

残念ながら、配列アプローチは複雑なパラメータに対して単一のコマンドにはうまく機能しますが、パイプなどのリダイレクトや複合コマンドでは機能しません。 –

+0

私の記事で提案したように、2つの配列を使うことができます。最悪のケースでは、パイプを強制することはできますが、2番目のステップでは何もしたくないときは、2番目の配列には "cat"だけが含まれます。 – Fred

+0

ちなみに、関数は多くの単純な問題にアプローチするための非常に良い方法ですが、コマンドラインをプログラム的に組み立てて引数として渡すという一般的な問題は、私の経験では非常に有用なものなので、仕事のための正しいツールではない場合もあります。 – Fred

関連する問題