私のもの強く打つスクリプトには、実行できるmysqldump blabla > dump.sql
多くのコンテンツが含まれています。mysq balbla < dump.sql
試運転モデル。
実際には、ポイントはrun
私が要求するすべてを実行する関数を作成することです。
run echo 'hello world'
run mysqldump blabla > dump.sql
run mysql blabla < dump.sql
run ssh blabla
# etc
run() {
if [[ "$(printenv DRY_RUN)" = "yes" ]]
then
echo "${@}"
else
${@}
fi
}
しかし、これはうまくいきません。
run "mysqldump -uuser -ppass dbase > dump.sql"
次のエラーが発生します。
mysqldump: テーブルが見つかりません: ">"
答え1
"${@}"
代わりに${@}
(withのように)を使用する必要がありますecho "${@}"
が、これが問題の原因ではありません。
その理由は、パラメータの置換前、コマンドライン解析の初期にリダイレクトが発生するためです。したがって、変数を>
コマンドラインに入れた後、シェルはもはやその変数を見つけません>
。
回答を投稿した後、重要な点が見つかりました。このように電話してください。
run mysqldump blabla > dump.sql
関数は合計を見ることがrun
できません。の出力もファイルにリダイレクトされるため、単一の環境変数を使用してすべてのリダイレクトを変更することはできません。したがって、次のようなものを使用する必要があります。下記をご覧ください。>
dump.sql
echo "${@}"
run --redirect dump.sql mysqldump blabla
2つの可能性があります。
それに固執し
"$@"
て使用してくださいeval
。もちろん、これは引用の悪夢につながる可能性があります。引用符を削除する前に、>
シェルがコマンドライン>
でデフォルトの内容を表示できるようにする以外のすべての項目を引用符で囲む必要があります。リダイレクトを個別に処理します。
run --redirect dump.sql mysqldump blabla run() { if [ "$1" == '--redirect' ]; then shift redirect_target="$1" shift else redirect_target='/dev/stdout' # works at least with Linux fi if [[ "$(printenv DRY_RUN)" = "yes" ]] then echo "${@}" else "${@}" > "$redirect_target" fi }
redirect_target='/dev/stdout'
if [ "$1" == '--redirect' ]
の四半期に配置すると、これを回避できます。else
if [[ "$(printenv DRY_RUN)" = "yes" ]]
if [[ "$(printenv DRY_RUN)" = "yes" ]] then if [ "$1" == '--redirect' ]; then # do not output "--redirect file" shift shift fi echo "${@}" else if [ "$1" == '--redirect' ]; then shift redirect_target="$1" shift "${@}" > "$redirect_target" else "${@}" fi fi
答え2
絵最近投稿した別の回答、トークン化がリダイレクトを開始するには遅すぎます(ただし、リダイレクトに影響を与えるには遅すぎません)。
eval
リンクされた投稿の他の回答で提案されているように、run commandを使用することも、使用することもできますが、bash -c "$*"
まだコマンドライン全体(リダイレクトを含む)を引用する必要があります。
ただし、コマンドを引用したくない場合は、bashがコマンドを実行せずに印刷のみを実行するように-nv
(noexec
および)を設定することが1つあります。verbose
そのため、run
ラッパーを使用するのではなく、スクリプトの先頭で次のようにします。
[[ $DRY_RUN = yes ]] && set -nv
答え3
使用"$@"
(二重引用符を含む):
run() {
if [[ "$(printenv DRY_RUN)" = "yes" ]]
then
echo "${@}"
else
"$@"
fi
}
それらがなければ、$@
単一のタグに展開されます。