Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
9
Help us understand the problem. What are the problem?
@ko1nksm

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

特に詳しく説明することもないですが [ ] (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
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
9
Help us understand the problem. What are the problem?