Bash:引用符付き引数を含むコマンドを関数に渡す

Bash:引用符付き引数を含むコマンドを関数に渡す

以下のbash機能があります。

function exe {
    echo -e "Execute: $1"
    # Loops every 3s, outputting '...' until command finished executing
    LOOP=0
    while true;
    do
        if ! [ $LOOP == 0 ]; then echo -e "..."; fi;
        sleep 3;
        LOOP=$LOOP+1
    done & ERROR="$($2 2>&1)" # Execute the command and capture output to variable

    status=$?
    kill $!; trap 'kill $!' SIGTERM

    if [ $status -ne 0 ];
    then
        echo -e "✖ Error" >&2
        echo -e "$ERROR" >&2
    else
        echo -e "✔ Success"
    fi
    return $status
}

目的は、次のように呼び出すことです。

exe "Update apt indexes" \
    "sudo apt-get update"

任意の出力:

Execute: Update apt indexes
...
...
...
...
✔ Success

渡されたコマンドで引用符で囲まれた文字列をパラメータとして使用しないと、正常に動作します。

たとえば、次は機能しません。

exe "Create self signed certificate" \
    "sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt -subj \"/C=GB/ST=London/L=London/O=Company Ltd/OU=IT Department/CN=dev.domain.local\""

set -x は、上記のコマンドが実行のために次のコマンドに変換されることを示します。

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt -subj '"/C=GB/ST=London/L=London/O=Confetti' Celebrations Ltd/OU=IT 'Department/CN=dev.sign-in.confetti.local"'

これは、単一引用符をたくさん選択してコマンドを無効にするようです。

この制限のないバージョンが必要です。どんなアイデアがありますか?

===============

提案やその他のバグ修正後の最終コードは次のとおりです。

exe () {
    echo -e "Execute: $1"
    LOOP=0
    while true;
    do
        if ! [ $LOOP == 0 ]; then echo -e "..."; fi;
        sleep 3;
        LOOP=$((LOOP+1))
    done & ERROR=$("${@:2}" 2>&1)
    status=$?
    kill $!; trap 'kill $!' SIGTERM

    if [ $status -ne 0 ];
    then
        echo -e "✖ Error" >&2
        echo -e "$ERROR" >&2
    else
        echo -e "✔ Success"
    fi
    return $status
}

この関数は放浪設定シェルスクリプトの「美化器」として使用され、次のように呼び出すことができます。

exe "Update apt indexes" sudo apt-get update

出力は次のように表示されます。

Execute: Update apt indexes
...
...
...
...
✔ Success

3秒未満持続するコマンドには進行状況出力は表示されません。

エラーが発生しない限り、エラー状態とコマンドの完全な出力を受け取ります。

主な目的は、stderrにメッセージを出力するときに放浪設定スクリプトによって表示される赤い線を削除することです。多くのコマンドは、メッセージを別のコマンドにリンクしないことが目的であるため、stderrに情報を正しく出力します。 Vagrant はメッセージを標準出力に出力します。これはエラーのように見えますが、実際にはエラーではなく、多くの構成メッセージが残る可能性があります。

この関数は、実行されたコマンドがゼロ以外の状態を返さない限り、stderrに印刷しません。これは、コマンドが失敗を示さない限り、赤いメッセージが表示されないことを意味します。コマンドがゼロ以外のメッセージで失敗を示す場合は、コマンドの出力全体をstderrに印刷して赤い線を表示します。

シェルスクリプトを使用すると、放浪設定がはるかにきれいになり、実際に赤いメッセージを注意深く観察し、その意味を知ることができます。

上記のコードで見逃したいくつかのビジュアル要素を含むバグラントで使用できる完全な機能はここにあります。https://gist.github.com/michaelward82/c1903f2b37a76975740e

エラーなしでexe関数を使用した出力の例: エラーのあるexe関数を使用した出力例

エラーのあるexe関数を使用した出力の例: エラーのあるexe関数を使用した出力例

実際のエラーなしでコマンドを直接実行したデフォルト出力は次のとおりです。 コマンドのデフォルト出力は、実際のエラーなしで直接実行されます。

ベストアンサー1

コマンド全体を文字列として渡したくない場合があります。シェルにはパラメータリストとしてリストがあり、リストをリストに渡す方がはるかに簡単です。

を書くのではなく、exe blah "blahh cmd"コマンドを直接作成し、exe blah blahh cmdコマンド全体を直接使用する必要がある場合はを使用してください。スライス拡張最初のパラメータに続くすべての項目を取得しますERROR=$("${@:1}" 2>&1)

shift伝統的にパラメータリスト全体を移動するには、「左」を使用できます(参考文献を参照help shift)。

f(){
    local j="$1"
    shift
    echo "$j,$3"
    shift 50
    echo "$1" # guess what "$@" is now?
}

f {1..100}

しかし、これは明らかにbashには必要ありません。

スライシングについて話したら、次も確認してみてください。ソートバッシュから。


ええと、それでも..を使用して文字列を直接実行できますが、eval単純なコマンド以上の機能を許可するため、これは通常悪いと見なされます。


スタイルのヒントとして、xxx()より短くてfunction xxx移植性の高い(POSIX-)を好みますfunction xxx()。 Bashでは同じです。

おすすめ記事