ローカライズされた店舗オプション

ローカライズされた店舗オプション

shopt関数のオプション値を一時的に変更したいと思います。

組み込み関数を使用して設定できるオプションは、関数本体内で設定setできます。local -以下はサンプルコードです

#!/bin/bash

# Enable the options globally 
set -u
[[ "$SHELLOPTS" =~ nounset ]] && echo "1: nounset enabled"
shopt -s "extglob"
[[ "$BASHOPTS" =~ extglob ]] && echo "1: extglob enabled"

fun () {
    #Enable the options locally just in fun
    local -
#    local BASHOPTS
    set +u
    [[ "$SHELLOPTS" =~ nounset ]] || echo "2: nounset disabled"
    shopt -u "extglob"
    [[ "$BASHOPTS" =~ extglob ]] || echo "2: extglob disabled"
}

fun

if [[ "$SHELLOPTS" =~ nounset ]]; then
    echo "3: nounset enabled"
else
    echo "3: nounset disabled"
fi

if [[ "$BASHOPTS" =~ extglob ]]; then
    echo "3: extglob enabled"
else
    echo "3: extglob disabled"
fi

出力を含む

1: nounset enabled
1: extglob enabled
2: nounset disabled
2: extglob disabled
3: nounset enabled
3: extglob disabled

ご覧のとおり、オプションはnounset関数本体に追加するだけでローカライズできます。local -私は同じshoptオプションが欲しいです。現在の回避策は、まずオプションが有効になっていることを確認することです。

if ! shopt -q extglob; then
    extglobchanged=1
    shopt -s extglob
fi

その後、最終的に以前の状態に戻ります。

[[ "$extglobchanged" == 1 ]] && shopt -u extglob

中間コードが失敗する可能性があるすべての状況を処理する必要があるため、これは良い解決策ではありません。 (関数が終了する前に上記の行が実行されていることを確認する必要があります。)

質問: オプションをローカライズできますかshopt

--編集 1--

やる気

私のbashツールキットには、ユーザーにYesまたはNoを問い合わせる機能があります。私はcaseパターンをorに関連付けるためにこの目的のために拡張globを使用します。これは私のコードです

 yesnoquery () {
    local extglobchanged=0
    local returnvalue=2
    while true; do
    if read -p "$1" answer; then
        if ! shopt -q extglob; then
        extglobchanged=1
        shopt -s extglob #enable for pattern matching
        fi
        eval '
        case "$answer" in
            @([Yy]|[Yy][Ee][Ss])) returnvalue=0;; #true
            @([Nn]|[Nn][Oo])) returnvalue=1;; #false
            * ) echo "Please answer \"y\" or \"n\"";;   
        esac
        '
        [[ "$extglobchanged" == 1 ]] && shopt -u extglob #revert changes
        [[ "$returnvalue" != 2 ]] && return "$returnvalue"
    else
        return 2 #reading returned error
    fi
    done
}

こんな些細なことをするには長い時間がかかるようです。shoptオプションextglobをローカライズできる場合は、caselikeから直接返すことができます@([Yy]|[Yy][Ee][Ss])) return 0;;。また、この[[ "$extglobchanged" == 1 ]]...行とその後の行は必要ありません。

主な問題

現在、関数が終了する可能性があるすべての場所に変更を元に戻すには、手動でコードを追加する必要がありますshopt

私の考えは、これらの変更をローカライズする必要があるということですlocal -。ローカライズのない他のソリューションは完璧です。

これが単に言語制限であれば、これは私の質問に対する答えでもあります。

ベストアンサー1

はい、可能です:

fun()
{
    local -
    # store state of all options.
    oldstate="$(shopt -p)"
    :
    :

    set +vx; eval "$oldstate"
}

特別な状況がありますerrexit

おすすめ記事