LoginSignup
43
19

More than 1 year has passed since last update.

シェルスクリプトの [ -a (AND) と -o (OR) ] は非推奨だかんね

Last updated at Posted at 2021-08-15

特に詳しく説明することもないですが [ ] (test) で使える演算子の -a (AND) と -o (OR) は POSIX では非推奨(廃止とマーク)となっているので移植性を重視する場合は使わないようにしましょう。[ 条件1 -a 条件2 ] の代わりに [ 条件1 ] && [ 条件2 ][ 条件1 -o 条件2 ] の代わりに [ 条件1 ] || [ 条件2 ] と書けば十分です。

-a-o が不要ということは ( ) があってもしょうがないのでこちらも廃止されます。複雑な条件式は避けた方が良いと思いますが、優先順位を指定したいのであれば [ 条件1 ] && { [ 条件2 ] || [ 条件3 ]; } のように { } を使用します。( )を使って [ 条件1 ] && ( [ 条件2 ] || [ 条件3 ] ) と書いても動きますがサブシェルが生成され遅くなるので避けたほうが良いです。

expression1 -a expression2
[OB XSI] True if both expression1 and expression2 are true; otherwise, false. The -a binary primary is left associative. It has a higher precedence than -o.

expression1 -o expression2
[OB XSI] True if either expression1 or expression2 is true; otherwise, false. The -o binary primary is left associative.

( expression )
[OB XSI] True if expression is true. False if expression is false. The parentheses can be used to alter the normal precedence and associativity.

[OB - Obsolescent]

The functionality described may be removed in a future version of this volume of POSIX.1-2017. Strictly Conforming POSIX Applications and Strictly Conforming XSI Applications shall not use obsolescent features.

Where applicable, the material is identified by use of the OB margin legend.

このように POSIX 曰く「将来削除される可能性があるからPOSIX に準拠するなら使ってはならない」とのことです(とは言え各シェルは互換性を保つために残すはずなので直ちに影響がでるとは思いませんが)。Issue 6 の頃は XSI 拡張オプション扱いだったのですが Issue 7 では廃止とマークされ、次の Issue 8 では見事に削除されます。廃止の理由は複雑な式だと曖昧で動作が信用ならないからとかかんとか。詳しくは POSIX を参照してください。

2021-09-10 追記 -a を使用した場合の具体的な違いを見つけたので追記します。

# Ubuntu 18.04
dash -c '[ ! "" -a "" ]' # $? = 1
bash -c '[ ! "" -a "" ]' # $? = 0
mksh -c '[ ! "" -a "" ]' # $? = 0
ksh -c  '[ ! "" -a "" ]' # $? = 1
posh -c '[ ! "" -a "" ]' # $? = 1
yash -c '[ ! "" -a "" ]' # $? = 0
zsh -c  '[ ! "" -a "" ]' # $? = 0
busybox ash -c '[ ! "" -a "" ]' # $? = 1
/usr/bin/[ ! "" -a "" ] # $? = 0

# FreeBSD 13.0
sh -c  '[ ! "" -a "" ]' # $? = 1 
ksh -c '[ ! "" -a "" ]' # $? = 1 

# Solaris 10
sh -c  '[ ! "" -a "" ]' # $? = 1  (Bourne シェル)
ksh -c '[ ! "" -a "" ]' # $? = 1 (ksh88)

[ "" -a "" ] の $? はどのシェルでも 1(偽)です。-a の優先度が ! "" よりも高い場合は [ ! "" -a "" ]0(真)になります。! "" の方が優先度が高い場合は 1(偽)となります。

bash -c '[ ! \( 1 = 1 \) -a "" ]' # $? = 1
bash -c '[ ! \( 1 = 2 \) -a "" ]' # $? = 1
bash -c '[ ! "" -a \( 1 = 1 \) ]' # $? = 0
bash -c '[ ! "" -a \( 1 = 2 \) ]' # $? = 1
43
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
19