11

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

#!/usr/bin/ksh

splitString() {

    string="abc@hotmail.com;xyz@gmail.com;uvw@yahoo.com"

    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 脚本的新手,谁能帮我理解上面示例中的变量范围?

4

2 回答 2

17

变量的默认范围是整个脚本。

但是,当您在函数内声明变量时,该变量将成为声明它的函数的局部变量。Ksh 具有动态作用域,因此该变量也可以在由声明该变量的函数调用的函数中访问。这在手册中有关功能的部分中进行了简要记录。请注意,在 AT&T ksh 中(相对于 pdksh 和衍生产品,以及 bash 和 zsh 的类似功能),这仅适用于使用function关键字定义的函数,而不适用于使用传统f () { … }语法定义的函数。在 AT&T ksh93 中,使用传统语法定义的函数中声明的所有变量都是全局变量。

声明变量的主要方法是使用typeset builtin。它总是使变量成为本地变量(在 AT&T ksh 中,仅在用 声明的函数中function)。如果您分配给一个变量而没有用 声明它typeset,它是全局的。

ksh 文档没有指定是set -A使变量成为局部变量还是全局变量,并且不同的版本也可以。在 ksh 93u、pdksh 或 mksh 下,该变量是全局变量,您的脚本会打印出该值。您似乎拥有 ksh88 或更旧版本的 ksh,其范围是本地的。我认为在函数str外部初始化会创建一个全局变量,但我不确定。

请注意,您应该使用局部变量来覆盖IFS: 的值,保存到另一个变量不仅笨拙,而且很脆弱,因为IFS如果未设置它就无法正确恢复。此外,您应该关闭 globbing,否则如果字符串包含 shell globbing 字符?*\[并且其中一个单词恰好匹配系统上的一个或多个文件,它将被扩展,例如set -A $stringwhere stringisa;*将导致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"
于 2012-08-17T10:28:55.083 回答
3

变量通常是全局的,从它们被定义的那一刻起,它们就被定义在其中。

typeset命令可以使它们在定义它们的函数中本地化,或者使它们自动导出(即使它们已更新)。

在联机帮助页或 Korn 的书中阅读“排版”和“整数”。

于 2012-08-17T08:33:46.797 回答