1

我习惯于使用这样的行来测试变量是否具有非空值(或给出消息和保释):

test $variable || (echo "Value of \$variable cannot be null."; exit 1)

我对在我的脚本中使用函数很陌生,但我有一个案例,我需要确保传递一个非空值或退出函数。但是,“或”情况的命令分组在函数内部的工作方式不同。我写了这个小测试脚本来演示:

 $ cat -n bubu.sh
 1  #!/bin/bash
 2
 3  read -p "give a value for variable \$foo: " -e -i "bar" foo
 4
 5  function firstfunc {
 6          test $1 || (echo "no value"; return 1)
 7          echo it looks like \"$1\" is  the first value of \$foo
 8          return 0
 9  }
10
11  function secondfunc {
12          test $1 || return 1
13          echo it looks like \"$1\" is the second value of \$foo
14          return 0
15  }
16  echo "first function:"
17  firstfunc $foo
18  echo returned $?
19
20  echo "second function:"
21  secondfunc $foo
22  echo returned $?

变量值的情况下的输出是这样的:

$ ./bubu.sh
give a value for variable $foo: bar
first function:
it looks like "bar" is the first value of $foo
returned 0
second function:
it looks like "bar" is the second value of $foo
returned 0

以及没有值的情况下的输出

$ ./bubu.sh
give a value for variable $foo:
first function:
no value
it looks like "" is the first value of $foo
returned 0
second function:
returned 1

在第一个函数中,当没有值时,我得到“或”命令组的第一个命令,并且“无值”回显,但返回命令被传递并执行函数的其余部分,直到返回.

为什么命令分组的括号在函数内部表现不同,或者我还缺少什么?

4

3 回答 3

4

正如其他人所提到的,parens 创建一个子shell,而 exit 或 return 命令指示 bash 从子shell 退出。你应该使用花括号。请注意,您可以使用 bash 参数替换以更简单的方式获得相同的效果。见下文。

即使在函数上下文的“外部”,您的行test $variable || (echo "Value of \$variable cannot be null."; exit 1)也不应该工作。例如:

$ cat t.sh 
#!/bin/bash

a="hello"
test $a || (echo "Value of \$variable cannot be null."; exit 1)
echo First test passed

a=
test $a || (echo "Value of \$variable cannot be null."; exit 1)
echo Second test passed

给出:

$ ./t.sh 
First test passed
Value of $variable cannot be null.
Second test passed
$ 

我们看到第二个echo运行,即使它不应该运行。使用花括号是要走的路。

$ cat t.sh 
#!/bin/bash

a="hello"
test $a || { echo "Value of \$variable cannot be null."; exit 1 ; }
echo First test passed

a=
test $a || { echo "Value of \$variable cannot be null."; exit 1 ; }
echo Second test passed
$ ./t.sh 
First test passed
Value of $variable cannot be null.
$

请注意,您可以使用 bash${parameter:?err_msg}构造进行参数替换:

$ cat t.sh 
#!/bin/bash

a="hello"
: ${a:?'a is null or undefined! Exiting..'}
echo First test passed

a=
: ${a:?'a is null or undefined! Exiting..'}
echo Second test passed

$ ./t.sh 
First test passed
./t.sh: line 9: a: a is null or undefined! Exiting..
$
于 2013-10-31T22:16:07.117 回答
1

()around将echo "no value"; return 1在子shell 中运行这些命令。return只会让你退出子shell,而不是完全退出函数。您可以使用它{}来实现没有子shell 的命令分组。还要确保在关闭之前return紧跟 a :;}

 6          test $1 || { echo "no value"; return 1; }

有关详细信息,请参阅Bash 手动命令分组部分

于 2013-10-31T21:26:17.067 回答
1

在括号内,由括号创建的子shell退出returnexit原因,而不是执行... || ...列表的shell。你想{...}改用。

function firstfunc {
    test $1 || { echo "no value"; return 1; }
    echo it looks like \"$1\" is  the first value of \$foo
    return 0
}

请注意,大括号比括号更挑剔:最后的命令必须后跟一个分号,并且您必须确保大括号与周围的字符用空格分隔。

于 2013-10-31T21:26:23.737 回答