30

nocasematchオプションの呼び出し元の設定を変更せずに使用するbash関数を作成しようとしています。関数の定義は次のとおりです。

is_hello_world() {
  shopt -s nocasematch
  [[ "$1" =~ "hello world" ]] 
}

私がそれを呼ぶ前に:

$ shopt nocasematch
nocasematch     off

あれを呼べ:

$ is_hello_world 'hello world' && echo Yes
Yes
$ is_hello_world 'Hello World' && echo Yes
Yes

予想どおりですがnocasematch、発信者の変更は次のとおりです。

$ shopt nocasematch
nocasematch     on

オプションを関数に対してローカルに変更する簡単な方法はありますか?

の戻り値を確認できることはわかっていますshopt -qが、それでも関数はこれを記憶し、終了する前にリセットする必要があることを意味します。

4

4 に答える 4

44

関数本体は、グループコマンド({})だけでなく、任意の複合コマンドにすることができます。サブシェルを使用します。

is_hello_world() (
  shopt -s nocasematch
  [[ "$1" =~ "hello world" ]] 
)
于 2012-08-29T14:00:15.463 に答える
21

RETURNトラップを使用する

RETURNトラップで指定されたコマンドは、シェル関数が...を返した後、実行が再開される前に実行されます。

[-p買い物をする]オプションを使用すると、出力が入力として再利用できる形式で表示されます。

https://www.gnu.org/software/bash/manual/bash.html

foobar() {
    trap "$(shopt -p extglob)" RETURN
    shopt -s extglob

    # ... your stuff here ...

}

テスト用

foobar() {
    trap "$(shopt -p extglob)" RETURN
    shopt -s extglob

    echo "inside foobar"
    shopt extglob # Display current setting for errexit option
}

main() {
    echo "inside main"
    shopt extglob # Display current setting for errexit option
    foobar
    echo "back inside main"
    shopt extglob # Display current setting for errexit option
}

テスト

$ main
inside main
extglob         off
inside foobar
extglob         on
back inside main
extglob         off

バリエーション:すべてのショップオプションをリセットするには、トラップステートメントを次のように変更します。

trap "$(shopt -p)" RETURN

バリエーション:設定されているすべてのオプションをリセットするには、トラップステートメントを次のように変更します。

trap "$(set +o)" RETURN

注:Bash 4.4以降、より良い方法があります:$-localを作成します。

バリエーション:すべてのセットすべてのショップオプションをリセットするには、トラップステートメントを次のように変更します。

trap "$(set +o); $(shopt -p)" RETURN

注: set +oと同等ですshopt -p -o

+ o 現在のオプション設定を、同じオプション設定を実現するコマンドとしてシェルに再入力するのに適した形式で標準出力に書き込みます。

オープングループベース仕様第7号、2018年版>セット

于 2018-06-12T02:35:20.773 に答える
13

この投稿日は2012年から知っていますが、次のこともできます(WindowsのGit Bash 1.8.4で動作するため、Linuxでも動作するはずです)。

function foobar() {
    local old=$(shopt -p extglob)
    shopt -s extglob

    ... your stuff here ...
    eval "$old"
}

この-pオプションは、オンのshopt -s extglob場合extglobは単に印刷し、そうでない場合は印刷しますshopt -u extglob

shopt -pオプションの全リストを印刷します。

于 2013-11-27T23:27:18.387 に答える
2

次のように、連想配列を使用して前の設定を記憶し、それを使用して以前の設定に戻すことができます。

shopt_set

declare -gA _shopt_restore
shopt_set() {
    local opt count
    for opt; do
        if ! shopt -q "$opt"; then
            echo "$opt not set, setting it"
            shopt -s "$opt"
            _shopt_restore[$opt]=1
            ((count++))
        else
            echo "$opt set already"
        fi
    done
}

shopt_unset

shopt_unset() {
    local opt restore_type
    for opt; do
        restore_type=${_shopt_restore[$opt]}
        if shopt -q "$opt"; then
            echo "$opt set, unsetting it"
            shopt -u "$opt"
            _shopt_restore[$opt]=2
        else
            echo "$opt unset already"
        fi
        if [[ $restore_type == 1 ]]; then
            unset _shopt_restore[$opt]
        fi
    done
}

shopt_restore

shopt_restore() {
    local opt opts restore_type
    if (($# > 0)); then
        opts=("$@")
    else
        opts=("${!_shopt_restore[@]}")
    fi
    for opt in "${opts[@]}"; do
        restore_type=${_shopt_restore[$opt]}
        case $restore_type in
        1)
            echo "unsetting $opt"
            shopt -u "$opt"
            unset _shopt_restore[$opt]
            ;;
        2)
            echo "setting $opt"
            shopt -s "$opt"
            unset _shopt_restore[$opt]
            ;;
        *)
            echo "$opt wasn't changed earlier"
            ;;
        esac
    done
}

次に、これらの関数を次のように使用します。

... some logic ...
shopt_set nullglob globstar      # set one or more shopt options
... logic that depends on the above shopt settings
shopt_restore nullglob globstar  # we are done, revert back to earlier setting

また

... some logic ...
shopt_set nullglob
... some more logic ...
shopt_set globstar
... some more logic involving shopt_set and shopt_unset ...
shopt_restore             # restore everything

ここで完全なソースコード:https ://github.com/codeforester/base/blob/master/lib/shopt.sh

于 2019-06-28T14:57:44.753 に答える