【読了】新しいシェルプログラミングの教科書
一介のソフトウェアエンジニアとしてシェルスクリプトくらいさらさらと書けますよね?......僕は書けません。というわけで「新しいシェルプログラミングの教科書」を読んだのでその際のメモです。
- Chapter01: シェルとは
- Chapter02: シェルスクリプトとは
- Chapter03: 基本
- Chapter04: 変数
- 値は文字列として解釈される
- $をつけて参照
- 明示的に参照するときは${}で囲む
- 変数のすぐ後ろに入力がある時使える
- 環境変数 = コマンドに引き継がれる変数
- コマンドから参照できるかどうか
- exportで変数を環境変数にする
- 慣例として変数名を大文字にする
- $1, $2, $3 … でスクリプトに渡された引数を参照できる
- $*, $@で全てを一度に参照できる
- 通常は$@で参照
- IFSは区切り文字を表し、参照する際は
echo "$IFS" | od -a
とする - 特殊パラメータ
- $# ... 引数の個数
- $? ... 前回コマンドの終了ステータス
- $$でプロセスIDを取得、tmpのファイル名などに利用
- declareコマンドで変数の型を宣言できる
- 整数型の場合代入の右辺は算術評価される
- 配列の宣言はvar=(a b c)、要素の参照は${var[i]}、追加は
var+=(value1 value2)
、削除はunset var[i]
、要素数の取得は${#var[@]}
- 連想配列を作る際はdeclare -Aで明示する必要がある
- Chapter05: 展開・クオーティング
- 展開の種類 ... パス名展開、ブレース展開、チルダ展開、パラメータ展開、コマンド置換、算術評価・展開、プロセス置換、履歴展開
- パス名展開
- マッチするファイルが存在する場合のみ有効
- 正規表現とまた違うマッチング規則なので注意
- ドットで始まるファイルを展開したいときは明示する必要がある
- ブレース展開
- マッチするファイルがなくてもいい
- 新しいファイルを作るときなどに利用
- マッチするファイルがなくてもいい
- チルダ展開
- ホームディレクトリのパスの展開
- パラメタ展開
- $varとか${var}とかのこと
- ${name:-value} ... デフォルト値の指定
- ${name:=value} ... デフォルト値を代入して返す
- ${name:?value} ... 値がない時のエラーメッセージの指定
- それぞれ
:
を除くと値が未設定の時のみの動作になり、空文字のときは空文字がそのまま返る - ${name:index:length}で文字列のスライシングができる
- ${#name} ... 文字数が返る
- ${name#pattern} ... 先頭から最短マッチでpatternを切り落とす
- ファイル名の取得
${path##*/}
- ファイル名の取得
- ${name%pattern} ... 末尾から最短マッチでpatternを切り落とす
- ディレクトリ名の取得
${path%/*}
- ディレクトリ名の取得
- それぞれ記号を二つ重ねると最長マッチになる
- ${name/pattern/substring} ... マッチするパターンを置換して返す
- 使い所不明
- コマンド置換
- $()と``は等価
- 算術評価・展開
((算術式))
... 終了ステータスが返る$((算術式))
... 評価結果が返る- exprコマンドでもいいけどこっちの方が早い
- letも等価だが、読みやすさを考えると代入のみに使うのがおすすめ
- プロセス置換
- <()で標準入力が二つ欲しい時にパイプラインの代わりとして使える
- (パイプラインの本質は一時ファイルなんだなー...。)
- 履歴展開
!
から始まる入力でコマンドの実行履歴を参照できる- スクリプトで使うことはまずない
- クオーティングで特殊文字を無効化する
- Chapter06: 制御構造
- 条件分岐
if (条件); then ~ elif ~ else ~ fi
- 条件はコマンドとして実行され、終了ステータスが0のとき真、0以外のとき偽に評価される
[]
はtestという"コマンド"- 演算子は覚えようね;)
- :はヌルコマンドといい、必ず正常終了する
command1 && command2
... command1の終了ステータスが0のときのみcommand2を実行するcommand1 || command2
... command1の終了ステータスが0以外のときのみcommand2を実行する[]
に対して[[]]
を使う最大のモチベーションは"読みやすさ"[[]]
はコマンドではなく構文- パターンマッチも使える
- ループ
for (変数) in (単語リスト) do ~ done
- break、continueが使える
case (文字列) in (パターン1) ~ ;; (パターン2) ~ ;; ... esac
*)
でデフォルト句を表す
- whileとその逆のuntilもあるよ
- 条件分岐
- Chapter07: リダイレクト・パイプ
- 標準入出力がファイルだからリダイレクト(元|先)つまり標準入出力の切り替え先もファイルだよ
(ファイルディスクリプタ番号)> (接続先ファイル)
が基本形&(ファイルディスクリプタ番号)
で他の接続先を指定できる- 標準出力にエラー出力を繋ぐ
2>&1
は定型文
- 標準出力にエラー出力を繋ぐ
- 出力を捨てるときは
/dev/null
を接続先に指定- 標準出力を捨てるのはifの条件部など
- 標準エラーを捨てるのはエラーを無視する時
- 両方捨てる決まり文句は
> /dev/null 2>&1
>
で上書き、>>
で追記(コマンド) <<< (終了文字列) ~ (終了文字列)
でヒアドクが書ける- 終了文字列をクオーティングすることでクオーティングのルールを適用できる
- パイプラインは一時ファイルが本質
{}
、()
で複数コマンドのグループ化ができる- 複数コマンドの出力をまとめて出力したいときとか
{}
は同一プロセス内、()
はサブシェル内で実行される→変数を参照する時注意
- Chapter08: 関数
- 三通りの書き方の中で
(関数名)() { ~ }
が一般的 - ローカルスコープで変数を宣言したいときは必ず
local
を使う - 引数の参照は同様に位置パラメータを使う
return
で終了ステータスを明示的に返すことができる
- 三通りの書き方の中で
- Chapter09: 組み込みコマンド
- :
- 無限ループが作れる
- printf
printf '%s\n' "~"
をよく使う
- command, builtin
- commandは組み込みコマンドと実行可能ファイル、builtinは組み込みコマンドから探す
- type
- コマンドの種別を調べたい時
- shift
- 解析済みの位置パラメータを削除するとき
- オプションの解析とかで意外とよく使う
- set
- 目的が複数あるという意味で一番UNIXらしくないコマンド
- 1)シェルのオプションの表示・変更、2)位置パラメータの設定
- unset
- 変数を削除したい時
- read
- 標準入力から一行取り出すとき
- ループのリスト部によく使う例えば
while IFS= read -r line do ~ done
- 入力行がlineに代入される、変数名を複数指定したときはIFS区切りでそれぞれ代入される
- trap
- 指定したシグナルを補足して指定の処理をする
- 終了前の後処理を記述したいときとか
- wait
- バックグラウンドで実行した処理の終了を待ちたいとき
- exec
- 現在のシェルをコマンドのプロセスに差し替えたいとき
- 現在のシェルのリダイレクト先を変更するときにも使う
- eval
- :
- Chapter10: 正規表現・文字列操作
- Chapter11: シェルスクリプトの実行
- Chapter12: 具体例
- Chapter13: シェル補完の書き方とか
- Chapter14: テスト・デバッグ
まとめ
「新しいLinuxの教科書」が読みやすかったので期待しましたが期待通りでした。シェルスクリプトを学ぼうという方には非常におすすめです。文法がわかったのでどんどん書いて身につけていこうというところですが実務ではあんまり使わないのでどうしたものか......。