どうも、Qiita初投稿です。
ブログとか含めて全く慣れていないので見づらいところはご勘弁を
そしてどちらかというと未だにシェルスクリプトですら慣れていないので、自分用の備忘録というのが一番
Linuxのコマンドつなぎについて
もともと簡単なシェルスクリプトとかなら書いたりしていて気にしていなかったのですが、最近仕事でよく作業手順書を書くことが増えてきました。
その際にコピペ用にワンライナーでコマンドを書くことが多いです。そうなってくると必ずいろんなコマンドを繋いでいく必要があるのでその際によく利用するようになりました。
こんな種類があるよ
CommandA <コマンド繫ぎ記号> CommandB
記号 | 名前 | 意味 |
---|---|---|
; | セミコロン | CommandAの実行後にCommandBを実行する |
& | アンパサント | CommandAと同時にCommandBを実行する |
| | パイプ | CommandAの実行結果をCommandBに渡す |
&& | アンパサントアンパサント | CommandAの実行が成功した際にCommandBを実行する |
|| | パイプパイプ | CommandAの実行が失敗した際にCommandBを実行する |
基本的に";"、"&"、"|"に関しては特に気にすること無く使えるかと
"&"使っている人見たことないですが
"&&"、"||"の制御演算子の挙動
昨日仕事でこの存在を思い出し使ってみて、ちょっとしたところでif文の代わり等で使えて便利!
もうif文は使わないぞ――と思ってみたらでかい罠がありました。
詳しくはこちら
https://qiita.com/miyu/items/f467c3fd693b5a8d5472
つまりは
"&&"と"||"を混ぜて3つのコマンドを繋げると危ない
【例】CommandAが成功したらCommandBを実行して、失敗したらCommandCを実行したい
CommandA && Command B || CommandC とやると
CommandA | CommandB | ComnmandC |
---|---|---|
成功 | 成功 | 実行無し |
失敗 | 実行無し | 実行する |
成功 | 失敗 | 実行する |
一番下のパターンが起こると困るってことですね。CommandBで終了コードが0以外だとCommandCが実行される状況になってしまうので。
こんなパターンはif文を正しく使いましょうということか、もしくはワンライナー諦めて2行で書くとか
ノリと勢いで何がなんでもif文使わず制御演算子だけでFizzBuzzやってやるぜって考えたけど結局以下になる。
for i in {1..100}
do
[ $(( ${i} % 3 )) -eq 0 ] && [ $(( ${i} % 5 )) -ne 0 ] && echo "Fizz"
[ $(( ${i} % 5 )) -eq 0 ] && [ $(( ${i} % 3 )) -ne 0 ] && echo "Buzz"
[ $(( ${i} % 3 )) -eq 0 ] && [ $(( ${i} % 5 )) -eq 0 ] && echo "FizzBuzz"
[ $(( ${i} % 3 )) -ne 0 ] && [ $(( ${i} % 5 )) -ne 0 ] && echo "${i}"
done
"&&"だけを使って全てのパターンを書き出すというね。
途中で"||"使おうとしたけど難しすぎた…うまいやり方知っている方は教えてください。
2019/6/3追記
angel_p_57さんのコメントからFizzBuzz作り直しました。
これでほとんど制御演算子メインで作れた感じ
for i in {1..100}
do
MSG=""
[ $(( ${i} % 3 )) -eq 0 ] && MSG="Fizz" ||
{ [ $(( ${i} % 5 )) -eq 0 ] && MSG="Buzz" || MSG=${i}; false;} &&
[ $(( ${i} % 5 )) -eq 0 ] && MSG=$MSG"Buzz"
echo $MSG
done
よくまぁ動いてますわ…
[ $(( ${i} % 5 )) -eq 0 ]
が冗長なのがイケてないっちゃないですね。
まぁ思ってた以上に動いてくれてそれなりに満足した。