成功するまで失敗時にコマンドを再試行しますが、別のフラグを使用してください。

成功するまで失敗時にコマンドを再試行しますが、別のフラグを使用してください。

そのため、失敗したか、コマンドラインエラーが発生して再試行しようとします。しかし、再試行するたびに別のフラグが表示されます。

私は失敗したときにコマンドを再試行する方法をすでに知っています。

while ! "$@"
do
  :
  sleep 1
done

たとえば、失敗したコマンドについて意図的に上記の関数を使用して説明します。

retry ls test # here this will usually fail and thus retry infinitely

私はこれを知っています:

  • 無限再試行(再試行されたコマンドが成功するか、シェルが成功したと解釈された終了コードを返すまで)
  • 失敗以外のいかなる種類のエラー/終了コードも考慮しません。

上記はすべて望み/期待される効果です。

私が追加したい唯一のことは、Nコマンドを「再試行」するときの追加フラグのサポートです(これを関数の引数として提供するか、適切に関数にハードコードする必要があります...)

私が試したことは次のとおりです。

bash
while ! "$(echo "$@" | sed "s/^pattern/pattern --otherflag/g")"
do
  :
  sleep 1
done

使用法:

retry ls pattern

新しいコマンドはどこにありますか?ls pattern --otherflag(明らかに失敗するでしょうが、それはポイントではありません。)

2番目の方法:

while ! "${@/pattern/pattern --otherflag}"
do
  :
  sleep 1
done

使い方は上記と同じです。

ここでは上記と同じ結果を提供します。

これで一見動作するように見えますが、提供/失敗したコマンドにある種の引用符(通常は引用符なし)が含まれている場合、出力/再試行コマンドから引用符は削除/無視されます。

したがって、上記の2つの方法/例によれば、このようなコマンドは引用ls pattern "file"符なしで実行されますls pattern --otherflag file(単一引用符を使用しても同じことが起こります)。file

この問題を解決するために私はこれを試しました回答機能を実行しquoteましたが、満足のいく結果が得られませんでした。また、失敗時に追加されたフラグを待機または使用するのではなく(再試行機能が開始されたときなど)、代わりに失敗する前に追加のフラグを使用して実行されているようです。

可能であれば、ブロック/条件を使用したくないので、ifできるだけ上記のスニペットに近づけることをお勧めします。優先bashおよび/またはsh代替。すべてのフィードバック/回答を歓迎します。

ベストアンサー1

スクリプトが呼び出さretry.shれ、シェル内のコマンドラインを介してretry.sh ls "foo bar"スクリプトの位置引数(パラメータ、つまり$1... $2)がおよびlsになりますfoo bar。引用符はシェルのコマンドラインからスペースやその他の特殊文字を保護する方法ですが、起動されたスクリプトには引用符が存在しなくなりました。代わりに、デフォルトでは文字列配列があります。

これで"$@"、さまざまな引数が正しく処理されます。各引数を別の単語に展開します。ただし、これは単語分割を使用してスペースに分割するのではなく、引数を文字列に連結し、コマンド全体の引用"$(echo "$@" | sed "s/^pattern/pattern --otherflag/g")"echoを置き換えて文字列として保持します。分割は、元のパラメータ間の分離が失われ、1つのパラメータがfoo bar2つのパラメータの合計に等しいため、役に立ちません。foobar

また、"${@/pattern/pattern --otherflag}"各位置引数に対して個別に置換が行われるため、引数を使用するとls2つのfoo bar単語"${@/ls/ls --otherflag}"が生成されますls --otherflag。これは、シェルコマンドラインで実行されているかls --otherflagのように文字通りというコマンドを探します。"ls --otherflag"


望むのは、、lsつまりフラグを追加パラメータとして追加することです。--otherflagfoo bar

できるここからすべての引数を取得し、$@シェル処理のためにエスケープし、一緒に接続して有効なコマンドラインを生成し、そのコマンドラインを編集してを使用してシェルに戻します。evalリストをリストとして扱う方が安全です。

最後にパラメータを追加するのは比較的簡単です。

#!/bin/sh
if ! "$@"; then
    echo "failed, retrying..."
    if ! "$@" --otherflag; then
        echo "nope, still failed"
    fi
fi

途中に1つを追加するには、配列またはスライスが必要です$@。たとえば、2番目の位置にフラグを追加します。

#!/bin/bash
if ! "$@"; then
    echo "failed, retrying..."
    if ! "$1" --otherflag "${@:2}"; then
        echo "nope, still failed"
    fi
fi

"${@:n:m}"初めて拡張インデックスから始まる位置パラメータN、またはリストの最後まで与えられませんでした。"$1"最初のパラメータ(と同じ"${@:1:1}")と"${@:2}"残りのパラメータも同じです。

やや関連:変数に保存されたコマンドをどのように実行できますか?

おすすめ記事