在Shell脚本中调用函数

在Shell脚本中调用函数

我在 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和右括号}位于同一行时,也需要使用分号。

相关内容