printfを使用して戻りコードをキャプチャし、配列をソートします。

printfを使用して戻りコードをキャプチャし、配列をソートします。

現在、うまく機能するbashコードがあります。しかし、構文が少し長いので、次のbashコードを減らす方法についての提案をいただきありがとうございます。

完全な参照のために、スクリプト全体がここにあります。https://gist.github.com/sacvalleytech/951f9eb98625f983f8f4dab623f5918b

# find new deps
# $1 -> file to search for dependencies
# $2 -> array of previous dependency changes (from siblings; used to invalidate cache); code not shown
# $3 -> hierarchy of dependencies (for circular ref checking); code not shown
DEP_OUT=( "$(changes "$DEP" "${DEP_OUT[*]}" "${DEP_HIERARCHY[*]}")" )

# >>> its really annoying to do this 
# >>> to capture the return code before sorting the array
# >>> sorting the array BEFORE causes the return code to be lost
[ "$?" -eq 0 ] && DEP_CHANGED=true

# sort values | normalize paths | uniq values
DEP_OUT=( $(printf "%s\n" "${DEP_OUT[@]}" | sort | trim | uniq) )

修正する:

意見に基づいて、次の解決策を思い出しました。

function format_array {
    if [ -t 0 ]; then
        local ARRAY_IN=( $@ )
    else
        readarray ARRAY_ARGS < /dev/stdin
        local ARRAY_IN=( $@ ${ARRAY_ARGS[@]} )
    fi

    echo $(printf "%s\n" "${ARRAY_IN[@]}" | sort | normalize_paths | uniq)
}

shopt -s lastpipe
shopt -so pipefail

DEP_OUT=( $(changes "$DEP" "${DEP_OUT[*]}" "${DEP_HIERARCHY[*]}" | format_array "${DEP_OUT[*]}") ) && \
DEP_CHANGED=true

これは正しい戻りコードを伝播するために重要です。

(コメントの1つがこの内容を簡単に言及したようですが、削除されたようですね)

shopt -s lastpipe
shopt -so pipefail

ベストアンサー1

再帰関数内で使用されるコードを単純化しようとしています。

改善したいのは、関数の終了コードをキャプチャすることです。

戻りコードは次のとおりです。いいえ情報を伝達する唯一の方法です。実際に情報を渡す最速の方法は、変数を使用することです。再帰関数では、親が値を再読み込みできるように、グローバル変数(ローカル変数として定義されていない)でなければなりません。この例では、戻りコードを1に設定する行は次のとおりです。

# return 1 (false) if $DEP_CHANGED = false && $DEP_FILE is cached
[ "$DEP_CHANGED" = false ] && (cached "$(dirname "$DEP_FILE")") && return 1

次のように変更できます。

# Inform that data didn't change
[ "$DEP_CHANGED" = false ] && 
    (cached "$(dirname "$DEP_FILE")") && 
    dep_changed_in_function=false

そしてそれに応じて:

for DEP in "${DEP_LIST[@]}"; do
    dep_changed_in_function=true

    # find new deps
    DEP_OUT=( "$(changes "$DEP" "${DEP_OUT[*]}" "${DEP_HIERARCHY[*]}")" )
    DEP_OUT=( $(printf "%s\n" "${DEP_OUT[@]}" | sort | trim | uniq) )

    # set $DEP_CHANGED flag
    [ "$dep_changed_in_function" -eq true ] && DEP_CHANGED=true
done

ただし、データ出力がすでにソートされている場合は、配列を処理DEP_OUTするための2番目の呼び出しを簡単に回避できます。changes

これは次の方法で簡単に行うことができます。

echo $(printf '%s\n' "${DEP_OUT[@]}" | sort | trim | uniq )

変える

echo "${DEP_OUT[@]}"

これにより、質問のコードセクションが次のように減少します。

for DEP in "${DEP_LIST[@]}"; do
    dep_changed_in_function=true

    DEP_OUT=( "$(changes "$DEP" "${DEP_OUT[*]}" "${DEP_HIERARCHY[*]}")" )

    # set $DEP_CHANGED flag
    DEP_CHANGED=$dep_changed_in_function
done

もちろん、dep_changed_in_function=trueこれは関数の先頭で設定できます。

おすすめ記事