我认为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 ]
Run Code Online (Sandbox Code Playgroud)
是什么赋予了?
Sté*_*las 11
typeset是 ksh93 的private(使用像perl's这样的静态范围my,而不是local动态范围)仅适用于使用 ksh 函数定义样式声明的函数:
function foo {
typeset var=whatever
...
}
Run Code Online (Sandbox Code Playgroud)
使用 Bourne 语法(或使用.命令(顺便说一句,也可以用于 ksh 样式的函数)),没有范围(当然$1,$2...除外$#)。因此,可以使用 Bourne 风格的函数来获取值或更改父上下文中变量的值或类型(尽管typeset -n也可以与 ksh 风格一起使用)。
在 ksh88 中,typeset正在使用 ksh 和 Bourne 函数定义样式进行动态范围界定。根据 David Korn 的说法,POSIX 没有指定 ksh 的变量范围,因为它是动态的(被认为是劣等的),这就是为什么他将其更改为静态范围ksh93(完全重写)。
但与此同时,其他 shell 已经实现了变量范围,它们都使用动态范围来模拟 ksh88。
zsh现在有一个private关键字来具有类似于ksh93's 的范围,除了local/typeset与动态范围类似 in ksh88。
要查看静态范围和动态范围之间的区别,请比较:
"$shell" -c 'function f { typeset a=1; g; echo "$a"; }
function g { echo "$a"; a=2; }
a=0; f'
Run Code Online (Sandbox Code Playgroud)
其中带有$shell==ksh93输出:
0
1
Run Code Online (Sandbox Code Playgroud)
并带有ksh88或bash输出:
1
2
Run Code Online (Sandbox Code Playgroud)
zsh:
$ zsh -c 'zmodload zsh/param/private
f() { private a=1; g; echo $a;}
g() { echo $a; a=2; }
a=0; f'
0
1
Run Code Online (Sandbox Code Playgroud)
为了能够在代码中使用本地范围移植到bash,zsh,ksh88 ksh93,pdksh,yash或dash/ FreeBSDsh的,你可以这样做:
[ -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
Run Code Online (Sandbox Code Playgroud)
然后将您的函数声明为:
kshdef foo
shdef foo()
{
mylocal var
var=value
...
}
Run Code Online (Sandbox Code Playgroud)
在任何情况下,local不同 shell 中的行为之间存在许多差异。除了上面提到的动态 vs 静态考虑之外,还有变量最初是否获得未设置或空值或从父作用域继承值。还有与readonly,的交互unset,无论local/typeset是关键字还是内置(影响 split+glob 处理)...
在 中使用 ksh 样式的函数定义还有其他含义,ksh93有关详细信息,请参阅手册页。