Travis CIに似た非常にコンパクトなバージョンの関数を作成しようとしています。travis_retry
。関数は、デフォルトで指定された引数をコマンドで3回試行し、繰り返し失敗すると失敗(1を返す)する高次関数でなければなりません。
以下は私が試したいくつかの試みですが、それらのどれも私の期待に達していませんでした。
retry() {
"${@}" || "${@}" || "${@}"
}
これは単純なコマンド(例echo ciao
:)では機能しているように見えますが、重要な式では失敗します。
$ retry if true; then echo hello; fi; false
bash: syntax error near unexpected token `then'
私は関数がhello
3回印刷して返すことを期待しました1
(false
最後に評価されたので)。
2番目の試みは次のとおりです。
retry() {
$* || $* || $*
}
これは以前と同じです。 3番目のバージョンも試しましたが、eval
当然動作しません。この時点で、ここにいくつかの基本が欠けていることが明らかであるので、試してみるのではなく理解したいと思います。
ベストアンサー1
関数を使用すると、複数の文字列引数のみを渡すことができるため、単純なコマンドの引数としてのみ解釈できます。任意のシェルコードを文字列として渡すことはできますが、関数にリテラル文字列として渡すためにコードを評価して引用する必要があります。
retry() { eval " $1" || eval " $1" || eval " $1"; }
retry 'if true; then echo hello; fi; false'
またはあなたのもの:
retry() { "$@" || "$@" || "$@"; }
と呼ばれる:
retry eval 'if true; then echo hello; fi; false'
ただし、エイリアスを使用すると、次のことができます。
alias 'retry{{={
attempts=0
until {' '}}=
}; do
if (( ++attempts >= 3 )); then
echo >&2 "Giving up after $attempts attempts"
! break
fi
done
}'
それから:
bash-5.0$ retry{{ echo test; false; }}
test
test
test
Giving up after 3 attempts
これは、Cのプリプロセッサマクロのように、コードが完全に解析される前にコードを読み取るとエイリアスが拡張されるために機能します。