私は次のような関数をエイリアスとして定義しました。
testif() {
([ $1 ]) && echo "true" || echo "false"
}
testit "1 == 2"
..それでは電話をかけることができます。強く打つシェルと出力はfalse
予想通りです。しかし、うまくいきません扱いにくい。 zshで同じ呼び出しの出力はtrue
。
- zshにこれらの関数を書くことはできますか?
- 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