変数のスコープを変数が宣言されている関数に制限する POSIX 準拠の方法はありますか? すなわち:
Testing()
{
TEST="testing"
}
Testing
echo "Test is: $TEST"
「Test is:」と出力する必要があります。declare、local、および typeset キーワードについて読んだことがありますが、必須の POSIX ビルトインではないようです。
私と一緒に地獄へ旅したいなら、私はそのeval
概念をより精巧に実装しました。
これは、準スコープ変数のアカウントを自動的に保持し、より使い慣れた構文で呼び出すことができ、ネストされたスコープを離れるときに変数を適切に設定解除します (単に null にするのではなく)。
ご覧のとおりpush_scope
、スコープに入り、_local
準ローカル変数を宣言しpop_scope
、スコープを離れます。_unset
変数の設定を解除するために使用しpop_scope
、そのスコープに戻ったときに再度設定を解除します。
your_func() {
push_scope
_local x="baby" y="you" z
x="can"
y="have"
z="whatever"
_unset z
push_scope
_local x="you"
_local y="like"
pop_scope
pop_scope
}
意味不明な変数名の接尾辞はすべて、名前の衝突に対して非常に安全です。
# Simulate entering of a nested variable scope
# To be used in conjunction with push_scope(), pop_scope(), and _local()
push_scope() {
SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D=$(( $SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D + 1 ))
}
# Store the present value of the specified variable(s), allowing use in a new scope.
# To be used in conjunction with push_scope(), pop_scope(), and _local()
#
# Parameters:
# $@ : string; name of variable to store the value of
scope_var() {
for varname_FB94CFD263CF11E89500036F7F345232 in "${@}"; do
eval "active_varnames_FB94CFD263CF11E89500036F7F345232=\"\${SCOPE${SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D}_VARNAMES}\""
# echo "Active varnames: ${active_varnames_FB94CFD263CF11E89500036F7F345232}"
case " ${active_varnames_FB94CFD263CF11E89500036F7F345232} " in
*" ${varname_FB94CFD263CF11E89500036F7F345232} "* )
# This variable was already stored in a previous call
# in the same scope. Do not store again.
# echo "Push \${varname_FB94CFD263CF11E89500036F7F345232}, but already stored."
:
;;
* )
if eval "[ -n \"\${${varname_FB94CFD263CF11E89500036F7F345232}+x}\" ]"; then
# Store the existing value from the previous scope.
# Only variables that were set (including set-but-empty) are stored
# echo "Pushing value of \$${varname_FB94CFD263CF11E89500036F7F345232}"
eval "SCOPE${SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D}_VARVALUE_${varname_FB94CFD263CF11E89500036F7F345232}=\"\${${varname_FB94CFD263CF11E89500036F7F345232}}\""
else
# Variable is unset. Do not store the value; an unstored
# value will be used to indicate its unset state. The
# variable name will still be registered.
# echo "Not pushing value of \$${varname_FB94CFD263CF11E89500036F7F345232}; was previously unset."
:
fi
# Add to list of variables managed in this scope.
# List of variable names is space-delimited.
eval "SCOPE${SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D}_VARNAMES=\"\${SCOPE${SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D}_VARNAMES}${varname_FB94CFD263CF11E89500036F7F345232} \""
;;
esac
unset active_varnames_FB94CFD263CF11E89500036F7F345232
done
unset varname_FB94CFD263CF11E89500036F7F345232
}
# Simulate declaration of a local variable
# To be used in conjunction with push_scope(), pop_scope(), and _local()
#
# This function is a convenience wrapper over scope_var().
#
# Can be called just like the local keyword.
# Example usage: _local foo="foofoofoo" bar="barbarbar" qux qaz=""
_local() {
for varcouple_44D4987063D111E8A46923403DDBE0C7 in "${@}"; do
# Example string: foo="barbarbar"
varname_44D4987063D111E8A46923403DDBE0C7="${varcouple_44D4987063D111E8A46923403DDBE0C7%%=*}"
varvalue_44D4987063D111E8A46923403DDBE0C7="${varcouple_44D4987063D111E8A46923403DDBE0C7#*=}"
varvalue_44D4987063D111E8A46923403DDBE0C7="${varvalue_44D4987063D111E8A46923403DDBE0C7#${varcouple_44D4987063D111E8A46923403DDBE0C7}}"
# Store the value for the previous scope.
scope_var "${varname_44D4987063D111E8A46923403DDBE0C7}"
# Set the value for this scope.
eval "${varname_44D4987063D111E8A46923403DDBE0C7}=\"\${varvalue_44D4987063D111E8A46923403DDBE0C7}\""
unset varname_44D4987063D111E8A46923403DDBE0C7
unset varvalue_44D4987063D111E8A46923403DDBE0C7
unset active_varnames_44D4987063D111E8A46923403DDBE0C7
done
unset varcouple_44D4987063D111E8A46923403DDBE0C7
}
# Simulate unsetting a local variable.
#
# This function is a convenience wrapper over scope_var().
#
# Can be called just like the unset keyword.
# Example usage: _unset foo bar qux
_unset() {
for varname_6E40DA2E63D211E88CE68BFA58FE2BCA in "${@}"; do
scope_var "${varname_6E40DA2E63D211E88CE68BFA58FE2BCA}"
unset "${varname_6E40DA2E63D211E88CE68BFA58FE2BCA}"
done
}
# Simulate exiting out of a nested variable scope
# To be used in conjunction with push_scope(), pop_scope(), and _local()
pop_scope() {
eval "varnames_2581E94263D011E88919B3D175643B87=\"\${SCOPE${SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D}_VARNAMES}\""
# Cannot iterate over $varnames by setting $IFS; $IFS does not work
# properly on zsh. Workaround using string manipulation.
while [ -n "${varnames_2581E94263D011E88919B3D175643B87}" ]; do
# Strip enclosing spaces from $varnames.
while true; do
varnames_old_2581E94263D011E88919B3D175643B87="${varnames_2581E94263D011E88919B3D175643B87}"
varnames_2581E94263D011E88919B3D175643B87="${varnames_2581E94263D011E88919B3D175643B87# }"
varnames_2581E94263D011E88919B3D175643B87="${varnames_2581E94263D011E88919B3D175643B87% }"
if [ "${varnames_2581E94263D011E88919B3D175643B87}" = "${varnames_2581E94263D011E88919B3D175643B87}" ]; then
break
fi
done
# Extract the variable name for the current iteration and delete it from the queue.
varname_2581E94263D011E88919B3D175643B87="${varnames_2581E94263D011E88919B3D175643B87%% *}"
varnames_2581E94263D011E88919B3D175643B87="${varnames_2581E94263D011E88919B3D175643B87#${varname_2581E94263D011E88919B3D175643B87}}"
# echo "pop_scope() iteration on \$SCOPE${SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D}_VARVALUE_${varname_2581E94263D011E88919B3D175643B87}"
# echo "varname: ${varname_2581E94263D011E88919B3D175643B87}"
if eval "[ -n \""\${SCOPE${SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D}_VARVALUE_${varname_2581E94263D011E88919B3D175643B87}+x}"\" ]"; then
# echo "Value found. Restoring value from previous scope."
# echo eval "${varname_2581E94263D011E88919B3D175643B87}=\"\${SCOPE${SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D}_VARVALUE_${varname_2581E94263D011E88919B3D175643B87}}\""
eval "${varname_2581E94263D011E88919B3D175643B87}=\"\${SCOPE${SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D}_VARVALUE_${varname_2581E94263D011E88919B3D175643B87}}\""
unset "SCOPE${SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D}_VARVALUE_${varname_2581E94263D011E88919B3D175643B87}"
else
# echo "Unsetting \$${varname_2581E94263D011E88919B3D175643B87}"
unset "${varname_2581E94263D011E88919B3D175643B87}"
fi
# Variable cleanup.
unset varnames_old_2581E94263D011E88919B3D175643B87
done
unset SCOPE${SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D}_VARNAMES
unset varname_2581E94263D011E88919B3D175643B87
unset varnames_2581E94263D011E88919B3D175643B87
SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D=$(( $SCOPENUM_CEDD88E463CF11E8A72A3F9E5F08767D - 1 ))
}
function myfunc {
構文を使用して関数をtypeset myvar
定義し、変数を定義するために使用します。myfunc(){
構文を使用するのではなく、そのように関数を定義すると、すべての一般的な Bourne シェル (bash、zsh、ksh '88 および '93) は、 で定義された変数typeset
(および typeset のようなエイリアス) をローカライズしますinteger
。
または、車輪を再発明します。どちらがあなたのボートを浮かせます。;)
編集:質問はPOSIXを求めていますが、これはPOSIX準拠の関数定義構文ではありませんが、尋ねた人は後のコメントでbashを使用していることを示しています。真の POSIX メカニズムでは、新しいサブシェルをフォークする追加のオーバーヘッドが必要になるため、別の関数定義構文と組み合わせて「typset」を使用することが最善の解決策です。