我以为typeset
是ksh
's local
,但这失败了,ksh93
尽管它在我所有其他typeset
支持 shell(bash、yash、zsh、pdksh)中都有效
#!/bin/ksh -ex
foo(){
typeset a b
a=0; b=1
return
}
a=a; b=b
foo
#confirm that the globals didn't change
[ "$a" = a ]
[ "$b" = b ]
是什么赋予了?
答案1
typeset
是 ksh93 的(使用像sprivate
一样的静态作用域,而不是动态作用域)仅适用于使用 ksh 函数定义样式声明的函数:perl
my
local
function foo {
typeset var=whatever
...
}
使用 Bourne 语法(或使用命令.
(顺便说一句,也可以在 ksh 样式函数上使用)),没有作用域(当然,除了$1
, $2
... $#
)。因此,可以使用 Bourne 风格的函数来获取值或更改父上下文中变量的值或类型(尽管typeset -n
也可以与 ksh 风格一起使用)。
在 ksh88 中,typeset
使用 ksh 和 Bourne 函数定义样式进行动态作用域。根据 David Korn 的说法,POSIX 没有指定 ksh 的变量范围,因为它是动态的(被认为较差)这就是为什么他将其更改为静态作用域ksh93
(完全重写)。
但与此同时,其他 shell 也实现了变量作用域,并且它们都使用动态的范围模仿 ksh88。
zsh
现在有一个关键字,除了/具有类似于 in 的动态作用域之外private
,还具有类似于 s 的作用域。ksh93
local
typeset
ksh88
要查看静态作用域和动态作用域之间的差异,请比较:
"$shell" -c 'function f { typeset a=1; g; echo "$a"; }
function g { echo "$a"; a=2; }
a=0; f'
其中$shell
==ksh93
输出:
0
1
并带有ksh88
orbash
输出:
1
2
zsh
:
$ zsh -c 'zmodload zsh/param/private
f() { private a=1; g; echo $a;}
g() { echo $a; a=2; }
a=0; f'
0
1
为了能够在可移植到bash
、zsh
、ksh88
ksh93
、pdksh
或/ shyash
的代码中使用本地作用域,您可以这样做:dash
FreeBSD
[ -n "$BASH_VERSION" ] && shopt -s expand_aliases
alias shdef= kshdef='#'
if type typeset > /dev/null 2>&1; then
alias mylocal=typeset
if (a=1; f() { typeset a=2; }; f; [ "$a" = 2 ]); then
alias shdef='#' kshdef='function'
fi
else
alias mylocal=local
fi
然后将您的函数声明为:
kshdef foo
shdef foo()
{
mylocal var
var=value
...
}
无论如何,local
不同 shell 中的行为之间存在许多差异。除了上面提到的动态与静态考虑之外,还有变量最初是否获得未设置或空值或从父作用域继承该值。还有与readonly
,的交互unset
,无论local
/typeset
是关键字还是内置的(影响 split+glob 处理)...
在 中使用 ksh 风格的函数定义还有其他含义ksh93
,有关详细信息,请参阅手册页。