我在 shell 中编写了一个简单的函数,它根据某些条件返回 0 或 1。让我将该函数命名为 foo
foo(){
...
...
}
现在我尝试在 if 条件下调用 foo ,如下所示:-
if ( foo $1 )
...
..
它工作正常。但是当我使用以下方法来调用时,我收到错误
if [ foo $1 ]
...
...
为什么它会抛出“预期一元运算符”错误?
答案1
当您使用:
if ( foo $1 )
您只需foo $1
在子 shell 中执行即可,并if
根据其退出状态进行操作。
当您使用:
if [ foo $1 ]
您正在尝试使用 shelltest
并富不是有效的测试操作员。您可以找到有效的测试操作员这里。
它不一定与您的问题相关,但您还应该始终引用变量,尤其是在 shell 测试括号内。只要存在某些东西,shell 测试就会成功。因此,即使使用有效的测试运算符,您也可能会得到不需要的结果:
$ unset var
$ [ -n $var ] && echo yes
yes
$ [ -n "$var" ] && echo yes
$ [ -n "" ] && echo yes
$ [ -n ] && echo yes
yes
$ [ foo ] && echo yes
yes
$ [ foo bar ] && echo yes
-bash: [: foo: unary operator expected
如果存在两个或多个字符串,并且其中一个字符串是有效的测试运算符,则 shell 测试中单个字符串的存在将评估为 true。
答案2
if
语句处理命令的退出状态。您的函数应该return
退出状态或回显字符串。就您的目的而言,return
似乎更合适。返回 0 表示函数成功完成,如果发生错误则返回任何其他值。例子:
$ foo(){ [ -e '/etc/passwd' ] && return 0; }
$ if foo; then echo "/etc/passwd exists"; fi
/etc/passwd exists
事实上,应该注意的是,您经常看到的 和if [ ... ]; then...
是完全相同的,if test ...; then...
因为[
和test
是相同的命令,并返回零或非零退出状态来指示是否发生错误。
答案3
除了其他用户所说的之外,if
复合命令的实际语法是:
if compound_list
then compound_list
[elif compound_list
then compound_list]...
[else compound_list]
fi
基本上compound_list
, 是任意数量命令的列表。if
将检查第一个命令的最后一个命令的退出代码COMPOUND_LIST
来决定执行什么( 、或 之一then ...
)。elif ...; then ...
else ...
这意味着你可以像这样重写它:
if foo "$1"; then
# Code to execute if foo returns 0
else
# Code to execute if foo returns 1
fi
如果foo
能够返回许多其他状态(2
, 3
, ..., 254
, 255
),那么使用case
会更好:
foo "$1"
case "$?" in
0) # Code to execute if foo returns 0 ;;
1) # Code to execute if foo returns 1 ;;
2) # Code to execute if foo returns 2 ;;
3) # Code to execute if foo returns 3 ;;
...
254) # Code to execute if foo returns 254 ;;
255) # Code to execute if foo returns 255 ;;
esac
编辑1
是 ”;”在语法中定义“$1”之后?
是的,正如 Kusalananda 所说,它被用作命令分隔符。
POSIX 定义以下命令:
- 简单命令:
[assignments] program [arguments] [redirections]
- 管道:
[!] command [pipe_operator command]...
- 列表:
- 与或列表:
pipeline [and-or_list_operator pipeline]...
- 化合物列表:
and-or_list [compound_list_operator and-or_list]
- 与或列表:
- 复合命令:
- 分组命令:
( compound_list )
{ compound_list; }
- 为了:
for name [in words]; do compound_list; done
- 案件:
case word in [[(] patterns ) compound_list ;;]... esac
- 如果:
if compound_list; then compound_list; [elif compound_list; then compound_list;]... [else compound_list;] fi
- 尽管:
while compound_list; do compound_list; done
- 直到:
until compound_list; do compound_list; done
- 分组命令:
- 函数定义命令:
name() compound_command [redirections]
Acompound_list_operator
可以是分号或换行符,它用在compound_list
/ for
/ case
/ if
/ while
/until
上下文中。
{ compound_list; }
请注意,当命令中的最后一个命令compound_list
和右括号}
位于同一行时,也需要使用分号。