ksh和bash脚本的区别

10

考虑以下脚本(用于 local_var2 的算术语法对此案例无关):

#!/bin/ksh

function my_func1
{
   typeset local_var1=one
   typeset local_var2
   (( local_var2 = 1 ))
   echo my_func1: local_var1 = $local_var1, local_var2 = $local_var2
}

my_func2()
{
   typeset local_var1=two
   typeset local_var2
   (( local_var2 = 2 ))
   echo my_func2: local_var1 = $local_var1, local_var2 = $local_var2
}
local_var1=0
local_var2=0
echo before functions: local_var1 = $local_var1, local_var2 = $local_var2

my_func1
echo after my_func1: local_var1 = $local_var1, local_var2 = $local_var2

my_func2
echo after my_func2: local_var1 = $local_var1, local_var2 = $local_var2

运行后将生成以下输出:

before functions: local_var1 = 0, local_var2 = 0
my_func1: local_var1 = one, local_var2 = 1
after my_func1: local_var1 = 0, local_var2 = 0
my_func2: local_var1 = two, local_var2 = 2
after my_func2: local_var1 = two, local_var2 = 2

(这并不是预期的结果!)

如果我在bash中运行相同的脚本,输出为:

before functions: local_var1 = 0, local_var2 = 0
my_func1: local_var1 = one, local_var2 = 1
after my_func1: local_var1 = 0, local_var2 = 0
my_func2: local_var1 = two, local_var2 = 2
after my_func2: local_var1 = 0, local_var2 = 0

(这是预期的结果!)


1
已测试并确认输出!虽然除了说ksh很糟糕,我没有其他解释;-) - zmo
使用代码中的set -vx(并根据Shell选择每个函数),您将看到变量内容在第二次调用时与预期明显不同。 - NeronLeVelu
2个回答

8
这是的一个怪异之处之一。 使用typeset命令将变量定义为局部范围的操作,只有在函数定义风格中才适用:
function func_name
{
}

不使用函数定义样式:
func_name()
{
}

使用func_name()风格,所有内容都是全局的。因此,ksh的行为与预期一致!!! 但是,bash在这方面显然比ksh更加明智。所以当使用typeset时,它将两个函数变量的作用域设置为局部。在ksh文档中有一个关于函数定义差异的FAQ条目。
Q18. What is the difference between function name and name()?

A18. In ksh88 these were the same.  However, the POSIX standard
    choose foo() for functions and defined System V Release 2
    semantics to them so that there are no local variables
    and so that traps are not scoped.  ksh93 keeps the ksh88
    semantics for functions defined as function name, and
    has changed the name() semantics to match the POSIX
    semantics.  Clearly, function name is more useful.

3

基于这个答案中的描述,你很可能正在运行 AT&T 版本的 ksh,其中内置的 typeset 仅在使用 function 关键字声明的函数中将变量设置为本地变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接