zshで関数に条件文をパラメータとして渡す方法は?

zshで関数に条件文をパラメータとして渡す方法は?

私は次のような関数をエイリアスとして定義しました。

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

testit "1 == 2"..それでは電話をかけることができます。強く打つシェルと出力は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)

$1他のshのようなシェルとは異なり、zshは実際には「最初の引数の値を取得する」を意味するので、単純な例もzshでは機能しません(ほとんどの拡張結果がnullの単語になると完全に削除されます)。 bashや他のshに似たシェルでは、$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

関連情報