2009-09-04 15 views
2

私は変数にコマンドの引数を格納しています。私がしたい最後のコマンドは次のとおりです。引用符はbash変数の中で尊重されていません

mock -r myconfig --define "debug_package %{nil}" --resultdir results --rebuild mypackage.src.rpm 

は、ここに私の試みです:

set -x # for debugging 

RESULTDIR=results 
MOCK_CONFIG="myconfig" 
MOCK_ARGS="-r $MOCK_CONFIG --define \"debug_package %{nil}\" --resultdir $RESULTDIR" 
cmd="mock $MOCK_ARGS --rebuild mypackage.src.rpm" 
$cmd 

結果は以下のとおりです。

+ RESULTDIR=results 
+ MOCK_CONFIG=myconfig 
+ MOCK_ARGS='-r myconfig --define "debug_package %{nil}" --resultdir results' 
+ cmd='mock -r myconfig --define "debug_package %{nil}" --resultdir results --rebuild mypackage.src.rpm' 
+ mock -r myconfig --define '"debug_package' '%{nil}"' --resultdir results --rebuild mypackage.src.rpm 
ERROR: Bad option for '--define' ("debug_package). Use --define 'macro expr' 

あなたが見ることができるように、--defineパラメータの引数がされていません適切に引用された。 --define私はそれが不完全ですdebug_packageだけを渡していると思う。

MOCK_ARGSを定義するときに引用符でさまざまなバリエーションを試しましたが、debug_package%{nil}の間のスペースをエスケープしようとしても。

この引数リストを作成してこのスクリプトからコマンドを実行するには、どのような引用符やエスケープを組み合わせて使用​​できますか?

EDIT:

私は変数に結果のコマンドを格納していた理由は、それがいくつかのログ記録を行う関数に渡されてしまうので、そのコマンドを実行しています。

また、私はthis FAQに出くわしました。これは、変数の代わりに配列を使うべきであることを示唆しています。私は配列を使って実験を始めましたが、今のところ解決策はありません。

+0

これはhttp://stackoverflow.com/questions/954390/echo-nested-quotation-marks-in-tcshの複製のようです。 –

+0

http://stackoverflow.com/questions/954390/echo- nested-quotation-marks-in-tcshは私のためには機能しません。 –

+0

[bashコマンドを引用符とアスタリスクで文字列として保存する方法]の複製が可能です(http://stackoverflow.com/questions/2005192/how-to-execute-a-bash-command-stored-as-a -string-with-quotes-and-asterisk) –

答えて

4

配列は、このようなもののために行く方法です。ここに私が思い付いたものです:$ *は(logコマンドに渡すのに適し)スペースで区切られたすべてのパラメータに展開

log_and_run() { 
    echo "$(date): running command: $*" 
    "[email protected]" 
    echo "$1 completed with status $?" 
} 

RESULTDIR=results 
MOCK_CONFIG="myconfig" 
MOCK_ARGS=(-r "$MOCK_CONFIG" --define "debug_package %{nil}" --resultdir "$RESULTDIR") 
cmd=(mock "${MOCK_ARGS[@]}" --rebuild mypackage.src.rpm) 
log_and_run "${cmd[@]}" 
# could also use: log_and_run mock "${MOCK_ARGS[@]}" --rebuild mypackage.src.rpm 

注意。 "$ @"はすべてのパラメータを別々の単語として展開します(log_and_runで使用されるように、最初は実行するコマンドとして扱われ、残りはパラメータとして使用されます)。同様に、 "$ {MOCK_ARGS [@]}"はMOCK_ARGSのすべての要素にスペースが含まれているかどうかにかかわらず、別々の単語として展開されます(したがって、MOCK_ARGSの各要素はcmdの要素になります)。

また、私はMOCK_CONFIGとRESULTDIRの拡張を引用しました。これはスペースが含まれていないので、ここでは必要ではありませんが、スペースを含むようになった場合(たとえば、外部からスクリプトに渡された場合など)に入るのは良い習慣です。 。

私は関数に追加のパラメータを渡す必要がある場合(ログに記録するファイル名の例を使用します)、array slicingを使用して、後のパラメータのみを分割してログ/実行:

log_and_run() { 
    echo "$(date): running command ${*:2}" >>"$1" 
    "${@:2}" 
    echo "$2 completed with status $?" >>"$1" 
} 
#... 
log_and_run test.log "${cmd[@]}" 

補遺:あなたがログにスペースを含むパラメータを引用したい場合、あなたは「手動」ログ文字列を作成し、必要な引用何でも行うことができます。例えば:これは(例えば)パラメータとブランクのパラメータにスペースではなく、パラメータ内の二重引用符を処理すること

log_and_run() { 
    local log_cmd="" 
    for arg in "[email protected]"; do 
     if [[ "$arg" == *" "* || -z "$arg" ]]; then 
      log_cmd="$log_cmd \"$arg\"" 
     else 
      log_cmd="$log_cmd $arg" 
     fi 
    done 
    echo "$(date): running command:$log_cmd" 
    ... 

注意。この "正しい"を行うことは、任意に複雑になる可能性があります。

また、私はlog_cmd文字列を構成する方法で、先頭のスペースで終わります。私はechoコマンドの前のスペースを省略することでこれを処理しました。実際にスペースをトリミングする必要がある場合は、"${log_cmd# }"を使用してください。

+0

ありがとう、これは私の問題を解決する!天才のストロークは完全な 'mock'コマンドを配列にすることでした。これは、 '$ *'や '$ @'の代わりに '$ 1'を使ってコマンドをログして実行する私の' log_and_run() '関数のリファクタリングにつながりました。私は '' debug_package%{nil} ''の引用符をログに表示することができませんでしたが、それは私が暮らすことができる細部です。 –

4

シェルスクリプトは悲惨なことがあります。多くの場合、cmd="blah $blah";$cmdblah $blahとは異なります。 $ cmdの代わりにeval $cmdを試すことができます。

はモックの代わりにこのperlスクリプトを呼び出してみてください。

#!/usr/bin/perl 
print join("\n",@ARGV),"\n"; 

あなたは引数リストが実際にあるものを見るために驚くかもしれ:私は推測しますが

-r 
myconfig 
--define 
"debug_package 
%{nil}" 
--resultdir 
results 
--rebuild 
mypackage.src.rpm 

「-x設定」出力一重引用符でこれを表示しようとしています。

私が最近学んだ一つの素敵なトリックは($*にはない)

function f { 
    echo "[email protected]" 
} 

が実際に適切Fに位置引数を転送することです。

それは "evalの" のように見えますが、おそらく意図し何を提供します:

set -x # for debugging 
RESULTDIR=results 
MOCK_CONFIG="myconfig" 
MOCK_ARGS="-r $MOCK_CONFIG "'--define "debug_package %{nil}" --resultdir '"$RESULTDIR" 
cmd="mock $MOCK_ARGS --rebuild mypackage.src.rpm" 
echo $cmd 
eval $cmd 

出力:

+ echo mock -r myconfig --define '"debug_package' '%{nil}"' --resultdir results --rebuild mypackage.src.rpm 
mock -r myconfig --define "debug_package %{nil}" --resultdir results --rebuild mypackage.src.rpm 
+ eval mock -r myconfig --define '"debug_package' '%{nil}"' --resultdir results --rebuild mypackage.src.rpm 
++ mock -r myconfig --define 'debug_package %{nil}' --resultdir results --rebuild mypackage.src.rpm 
-r 
myconfig 
--define 
debug_package %{nil} 
--resultdir 
results 
--rebuild 
mypackage.src.rpm 
+2

ありがとうございました。 –

関連する問題