unix KSH中变量的范围

42fyovps  于 2023-10-18  发布在  Unix
关注(0)|答案(2)|浏览(192)

我已经写了一个示例KornShell函数来拆分一个String,将其放入一个数组中,然后打印出值。代码如下

#!/usr/bin/ksh

splitString() {

    string="[email protected];[email protected];[email protected]"

    oIFS="$IFS"; 
    IFS=';' 
    set -A str $string
    IFS="$oIFS"
}

splitString
echo "strings count = ${#str[@]}"
echo "first : ${str[0]}";
echo "second: ${str[1]}";
echo "third : ${str[2]}";

现在echo并没有打印出数组的值,所以我假设它与定义的数组的作用域有关。
我是Shell脚本的新手,谁能帮助我理解上面例子中变量的作用域?

shstlldc

shstlldc1#

变量的默认作用域是整个脚本。
然而,当你在函数中声明一个变量时,这个变量对于声明它的函数来说是局部的。Ksh具有动态作用域,因此在声明变量的函数调用的函数中也可以访问变量。这在手册的功能部分有简要的说明。请注意,在AT&T ksh中(与pdksh和衍生物以及bash和zsh的类似功能相反),这仅适用于使用function关键字定义的函数,而不适用于使用传统f () { … }语法定义的函数。在AT&T ksh93中,所有用传统语法定义的函数中声明的变量都是全局变量。
声明变量的主要方式是使用typeset内置函数。它总是使变量成为局部变量(在AT&T ksh中,仅在用function声明的函数中)。如果你在没有用typeset声明的情况下赋值给一个变量,它就是全局变量。
ksh文档没有指定set -A是将变量设为局部变量还是全局变量,不同的版本都是这样。在ksh 93u、pdksh或mksh下,变量是全局变量,脚本会打印出值。你似乎有ksh88或旧版本的ksh,其中作用域是本地的。我认为在函数外部初始化str会创建一个全局变量,但我不确定。
请注意,您应该使用局部变量来覆盖IFS的值:保存到另一个变量不仅笨拙,而且脆弱,因为如果它未被设置,它不会正确恢复IFS。此外,您应该关闭globbing,因为否则如果字符串包含shell globbing字符?*\[,并且其中一个单词恰好匹配系统上的一个或多个文件,则它将被扩展,例如。set -A $string其中stringa;*将导致str包含当前目录中的文件名列表。

set -A str
function splitString {
  typeset IFS=';' globbing=1
  case $- in *f*) globbing=;; esac
  set -f
  set -A str $string
  if [ -n "$globbing" ]; then set +f; fi
}
splitString "$string"
y1aodyip

y1aodyip2#

变量从定义之时起,对于它们所定义的shell来说通常是全局的。
typeset命令可以使它们在定义它们的函数中本地化,或者使它们自动导出(即使它们被更新)。
阅读手册页或Korn的书中的“typelines”和“integer”。

相关问题