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をローカライズできる場合は、case
likeから直接返すことができます@([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
。