如何将条件语句作为参数传递给 zsh 中的函数?

如何将条件语句作为参数传递给 zsh 中的函数?

我定义了一个类似于以下的函数(作为别名),

testif() {
    ([ $1 ]) && echo "true" || echo "false"
}

..然后就可以打电话testit "1 == 2"巴什shell 和输出false符合预期。但它不起作用桀骜。 zsh 中同一调用的输出是true

  1. 是否可以为 zsh 编写这样的函数?
  2. 为什么 zsh 输出错误? zsh bash 不应该兼容吗?

答案1

除了非常简单的例子之外,你所做的在 bash 中也不起作用。

$ testif 'hello world = hello world'
bash: [: too many arguments
false
$ testif '"hello world" = "hello world"'
bash: [: too many arguments
false
$ testif '* = *'
(usually false with an error message, but it depends on the files in the current directory)

即使你的简单示例在 zsh 中也不起作用,因为与其他类似 sh 的 shell 不同,在 zsh 中,它的$1真正含义是“获取第一个参数的值”(几乎是:如果扩展导致空字,则将其完全删除)。在 bash 和其他类似 sh 的 shell 中,$1意味着“获取第一个参数的值,将其拆分为单词,并将每个单词视为一个全局模式”,这几乎不是您想要的。


test您可以在/single-brackets 命令的语法中传递条件,如下所示分离论据。

testif () {
  if [ "$@" ]; then echo true; else echo false; fi
}

这是可行的(有命令的限制[,例如 no&&||操作符。

$ testif '*' = '*'
true
$ testif hello = hello
true
$ testif 'hello world' = 'hello world'
true
$ testif 0 = 00
false
$ testif 0 -eq 00
true

不过,很少有充分的理由来传递[条件。您不妨传递整个命令。这不仅可以让您传递其他类型的条件(例如grep …if systemctl is-active …),而且如果您需要的不仅仅是一个简单的命令,您可以定义一个辅助函数。

testif () {
  if "$@"; then echo "true"; else echo "false"; fi
}
$ testif [ 'hello world' = 'hello world' ]
true
$ testif grep -q : /etc/passwd
true

另一种方法是将整个命令作为单个字符串传递,并eval在函数内部使用。

testif () {
  if eval "$1"; then echo true; else echo false; fi
}
$ testif '[ "hello world" = "hello world" ]'
true
$ testif '[ "hello world" = "h*" ]'
false
$ testif '[[ "hello world" = "h*" ]]'
false
$ testif '[[ "hello world" = h* ]]'
true

相关内容