以非实例化变量为条件

时间:2019-05-28 14:29:46

标签: bash

我是Bash脚本的新手,对C类型语言有更多的经验。我编写了一些带有条件的脚本,该脚本检查非实例化变量的值,如果该值不存在或与值匹配则设置该变量。最重要的是,整个过程都在for循环中。像这样:

for i in ${!my_array[@]}; do 
   if [ $my_array[i] = true ] 
      #do something
   else
      my_array[i]=true;
   fi
done

这将导致Java中的空指针失败,因为my_array [i]直到被检查后才实例化。这是Bash的良好做法吗?我的脚本按我设计的方式工作,但是我了解到,仅仅因为kluge现在可以工作,并不意味着它将来就可以工作。

谢谢!

2 个答案:

答案 0 :(得分:0)

您会发现this page on parameter expansion有帮助,还有this one有条件。

测试变量的一种简单方法是检查其非零长度。

if [[ -n "$var" ]]
then : do stuff ...

我也想使访问不存在的变量致命。这意味着额外的工作,但安全性更高。

set -u # unset vars are fatal to access without exception handling
if [[ -n "${var:-}" ]] # handles unset during check
then : do stuff ...

答案 1 :(得分:0)

默认情况下,在shell脚本中引用未定义(或“未设置”)变量名只会给出空字符串。但这是一个例外:如果外壳程序使用-u选项运行,或者其中已经运行set -u,则未设置变量的扩展将被视为错误,并且(如果外壳程序不是交互式的)会导致外壳程序退出。 Bash也将这一原理应用于数组元素:

$ array=(zero one two)
$ echo "${array[3]}"

$ echo "array[3] = '${array[3]}'"
array[3] = ''
$ set -u
$ echo "array[3] = '${array[3]}'"
-bash: array[3]: unbound variable

如果变量(或数组元素)未定义和/或为空(定义为空字符串),还可以使用修饰符来控制扩展操作:

$ array=(zero one '')
$ echo "array[2] is ${array[2]-unset}, array[3] is ${array[3]-unset}"
array[2] is , array[3] is unset
$ echo "array[2] is ${array[2]:-unset or empty}, array[3] is ${array[3]:-unset or empty}"
array[2] is unset or empty, array[3] is unset or empty

还有许多其他变体,请参见the POSIX shell syntax standard,第2.6.2节(参数扩展)。

顺便说一句,除了纯变量引用之外,您确实需要在其他任何地方使用花括号(就像我上面所做的那样)。 $name[2]是对普通变量name(如果是数组则为元素0)的引用,后跟字符串“ [2]”;另一方面,${name[2]}是对数组name的元素2的引用。另外,您几乎总是希望将变量引用包装在双引号中(或将其包含在双引号字符串中),以防止外壳程序“有效地”将其拆分为单词和/或将其扩展为匹配文件列表。例如,此测试:

if [ $my_array[i] = true ]

(大部分)等效于:

if [ ${my_array[0]}[i] = true ]

...这根本不是您想要的。但是这个:

if [ ${my_array[i]} = true ]

仍然不起作用,因为如果my_array[i]未设置(或为空),它将扩展为以下内容:

if [ = true ]

...这是错误的测试表达式语法。您想要这个:

if [ "${my_array[i]}" = true ]