初歩のシェルスクリプトで遊ぶ[シェルスクリプトの注意点はどこだろう(1)]
「シェルスクリプトの勘所」っぽい内容ですが、私が今、気をつけてるポイントというだけです。私は素人なだけでなく単なる初心者で、解説記事を書く実力はありません。半年も経てば私も気が変わってる可能性は高いです。参考程度にしてください。
そこまで自信が無いなら書くなよ、って気が自分でもするんだけれども……曖昧な考えをまとめるのに、書くのってちょうどいいので。
- Ubuntu20.04
- dashとbash
パイプはブレース「{}」で括って繋ぐのが基本、ブレース無しは省略した結果
いわゆる「はじめてのシェルの使い方入門」だと、パイプはコマンドどうしを直接に繋げる書き方で紹介されます。
$ ls | wc
スクリプトを書くときは、端末エミュレータでコマンドを叩くときとは別です。
パイプはブレースで括るのが基本、ブレースが無いのは省略した結果だ、と意識していると、便利です。
#!/bin/sh { ls } | { wc }
パイプはコマンド一つどうし、whileループやforループと直結することが多いです。
しかし直結せずにブレースでくくってから繋げると、簡単な作業が簡単にできることが増えます。
#!/bin/sh # 1行目を最終行に移動する echo 'ヘッダー行 111111 222222 333333 444444' | { read Line cat - echo "${Line}" }
・実行結果
111111 222222 333333 444444 ヘッダー行
「テキストの行単位処理といえばwhile read」ですが、これをブレース無しで初めて書くと、定番の失敗をするわけです。
#!/bin/sh # 1行目を最終行に移動したいができない lineNo='0' firstLine='1行目を入れておくシェル変数' echo 'ヘッダー行 111111 222222 333333 444444' | while read Line do lineNo=$(( ${lineNo} + 1 )) if test "${lineNo}" -eq 1 ; then firstLine="${Line}" continue fi echo "${Line}" done echo "${firstLine}"
・処理結果
111111 222222 333333 444444 1行目を入れておくシェル変数
こういうとき、結局はブレースで括って解決します。
#!/bin/sh # 1行目を最終行に移動したいができなかった lineNo='0' firstLine='1行目を入れておくシェル変数' echo 'ヘッダー行 111111 222222 333333 444444' | { while read Line do lineNo=$(( ${lineNo} + 1 )) if test "${lineNo}" -eq 1 ; then firstLine="${Line}" continue fi echo "${Line}" done echo "${firstLine}" }
・処理結果
111111 222222 333333 444444 ヘッダー行
シェル変数「firstLine」の中身を「while read」の外に持ち出せるわけですが、やっぱりこれもブレースが必要です。
そして、ブレースで括るならば、単に1行目を最終行に移動したいだけの簡単な処理なら、最初のスクリプトでも十分です。
1行目だけでなく、2行目でもいけますね。
#!/bin/sh # 2行目を最終行に移動する echo 'ヘッダー行 111111 222222 333333 444444' | { read Line echo "${Line}" read Line cat - echo "${Line}" }
・実行結果
ヘッダー行 222222 333333 444444 111111
さらに例えば「1行目のみ削って2行目以降をwhile readで処理したい」ときは、
#!/bin/sh # 1行目を削って残りは while read echo 'ヘッダー行 111111 222222 333333 444444' | { # 1行目のみ読み込むが、出力はしない。 read Line # 2行目以降を読み込み、処理してから出力する。 while read Line do echo ____"${Line}"____ done }
・処理結果
____111111____ ____222222____ ____333333____ ____444444____
コマンドをふたつ組み合わせてパイプに繋ぐときも、ブレースで括れば難しいことなく、そのまま書けます。
#!/bin/sh # 連番を増減させてパイプに繋ぐ { # 1 2 3 seq 1 3 # 4 3 2 1 seq 4 -1 1 } | { cat - }
・処理結果
1 2 3 4 3 2 1