はじめに
こんにちは、入社1年目の人間
です。
今回はシェルスクリプトの基本文法について簡単にまとめようと思います。
目次
1. きっかけ
2. 実行環境
3. シェルの基礎
4. まとめ
5. 参考
1. きっかけ
これから先、インフラ系のお仕事をしていきたいと考えていますが、知識が全くないのでインフラ系の雑誌を読みました。その際に、目に留まったのがシェルスクリプトだったので自分なりにまとめてみようと思いました。
2. 実行環境
今回はWindows PowerShellとUbuntuを実行環境として使用しました。PowerShellでUbuntuを起動し、その後はUbuntu上でLinuxコマンドやシェルスクリプトの作成・実行を行いました。
Ubuntuとは
コミュニティ により開発されているオペレーティングシステム
初心者でも直感的に使いやすいよう設計された、無料で利用できるオープンソース
3. シェルの基礎
パラメータと変数
-
パラメータ
- 割り当てられた値を持っている
- 名前、数値、特殊文字で示される(変数、位置パラメータ、特殊パラメータ)
-
変数
- 名前が付けられたパラメータ
- 名前が付けられたパラメータ
-
シェル関数
- 実行中のシェルの環境でのみ利用できる
- 実行中のシェルの環境でのみ利用できる
パラメータの値を利用するにはパラメータ展開と呼ばれる形式の1つである${parameter}を使います。
※ほかの文字列との境界があいまいにならないのであれば「{}」を省略した「$parameter」の形式もできます。
$ name=value #変数の定義
$ echo "${name}" #パラメータ展開
value
【注意】
$ name▽=▽value のように変数定義で=(イコール)の前後にスペース(▽)を空けるとエラーが発生します。スペースは空けずに詰めて書きましょう。
ポイント
シェルから実行されるコマンドで利用できる変数(いわゆる環境変数)として利用するにはexportコマンドを利用して変数にexport属性を付与します。
$ export name
$ export name=value #初期化も可能
-
位置パラメータ
- シェルや関数の引数の位置を数値で表したもの
- 例として1個目の引数はパラメータ「1」、2個目の引数はパラメータ「2」になる
パラメータ展開により「$1」、「$2」として利用できる
-
特殊パラメータ
| 特殊パラメータ | 説明 |
|---|---|
| @ | 位置パラメータに展開 |
| * | 位置パラメータに展開して結合 |
| # | 位置パラメータの数 |
| ? | 終了ステータス |
| $ | プロセスID |
| 0 | シェルやシェルスクリプトの名前 |
引用
文字列コマンドの引数に与えたり変数に格納したりするときに、以下の引用の形式が使えます。
| 引用の形式 | 特徴 |
|---|---|
| '...' | 文字通りの意味を保持する |
| "..." | パラメータ展開やコマンド置換や算術展開が利用できる |
| $'...' | 「\」で始まるエスケープシーケンスが利用できる |
※「...」は任意の文字列
$ echo "name=${name}" #変数の値に置換
name=value
パターンマッチング
文字列に一致するパターンを指定するために以下のような文字列が利用できます。
| 文字 | 説明 |
|---|---|
| ? | 1個の文字に一致する |
| * | 0個以上の文字に一致する |
| [...] | 指定した文字の集合の1個の文字に一致する(ブラケット表現) |
シェルの引数でパターンマッチングの文字を利用すると、パス名展開という機能によりドット(.)で始まるファイル名を除いたパターンに一致するファイル名が展開されます。
一致するファイル名がなければ展開されません。
$ echo *.txt #ファイル名のパターン
foo.txt bar.txt #パターンに一致するファイル名が返される
「"*.txt"」のように引用の形式で記述するとパス名は展開されません。
また、「[...]」の形式のブラケット表現を使うと文字の集合を扱えます。
例えば「[ab]」はaかbに一致します。範囲を意味する「-」を用いた「[a-z]」はaからzまでの任意の1文字に一致します。
リダイレクトとパイプ
-
リダイレクト
- コマンドの入力先や 出力先を変更する機能
- コマンドの入力先や 出力先を変更する機能
▼リダイレクト
| 形式 | nのデフォルト | 説明 | 例 |
|---|---|---|---|
| [n]<file | 0(標準入力) | 入力をファイルfileにリダイレクト | cat < in.txt |
| [n]>file | 1(標準入力) | 出力をファイルfileにリダイレクト | echo foo > out.txt |
| [n]>>file | 1(標準入力) | 追記出力をファイルfileにリダイレクト | echo bar >> out.txt |
| [n]>&m | 1(標準入力) | 出力ファイル記述子をファイル記述子mに複製する | echo foo 1>&2 |
| [n]<<delimiter | 0(標準入力) | ヒアドキュメント | cat << EOT |
上記に示す形式を使用するとファイルにリダイレクトできます。
#入力
$ cat < in.txt #in.txtの内容が表示される
出力の場合は出力先のファイルがすでに存在していれば、ファイルの内容が削除させてから出力されます。
#出力
$ echo foo > out.txt
標準出力と標準エラーの両方を同じファイルに出力したいときには「2>&1」のようにして標準エラーを標準出力に複製します。
また、複数のリダイレクトが記述されていときには左から右へと評価されるため、順番が意味を持ちます。
#複製
$ cat in.txt > out.txt 2>&1
後続行の内容を入力にリダイレクトするには<<delimiterの形式で指定します。
delimiterが入力の終わりを示す区切り文字になります。
ヒアドキュメント
#複製
$ cat <<EOT
foo
bar
EOT #1行目にfoo、2行目にbarと表示される
-
パイプ
- 「|」のことで、コマンドの標準出力と別のコマンドの標準入力に接続できる
$sort data.txt | uniq
#data.txtの内容を並び替えて重複行を省いた内容が表示される
シェルスクリプトの構成
構成については例を用いて説明します。
① #!/bin/sh
② # コメント
③ echo "$1"
④ exit 0
①のように先頭行にはシバンとして利用するシェルを指定します。
②のように「#」に続く文字列はコメントです。コメントは改行で終了します。
③と④のようにコマンドを記述できます。
③はシェルスクリプトの1個目の引数を「$1」として取得して出力します。
④の「exit」はシェルスクリプトを指定した終了ステータスで終了させます。
終了ステータスは0が成功で、0以外が失敗を意味します。
以下が実行例です☟
$ ./echo.sh 'Hello, World!' #シェルスクリプトecho.shを実行
Hello, World! #1個目の引数が表示される
$ echo $? #終了ステータスを表示
0
エラー発生時に中断する方法
シェルスクリプトはデフォルトではコマンドにエラーが発生しても終了せずに後続のコマンドを実行します。これは前のコマンドの結果を利用して後続のコマンドを実行するときには、想定していない結果が生じます。
これを防ぐためには...
☞ 「set -e」コマンドを記述し、errexitオプションを設定します。
これによりコマンドにエラーが発生したら終了します。次のスクリプトを実行するとfalseコマンドで終了します。
#!/bin/sh
set -e
false
echo "OK"
展開
-
パラメータ展開
- 「${expression}」の形式
一番単純な「${parameter}」の形式は単にパラメータparameterの値に置換されます。
以下は、パラメータ(変数)nameの値としてvalueを出力します。
#!/bin/sh
name='value'
echo "${name}"
▼パラメータが未定義や空であるときのパラメータ展開
| パラメータ展開 | 説明 |
|---|---|
| ${parameter:-word} | 未定義や空のときにwordを使う |
| ${parameter:=word} | 未定義や空のときにwordをparameterに割り当てる |
| ${parameter:?word} | 未定義や空のときにwordをエラーとして出力して終了する |
上記の式を用いるとパラメータが未定義(unset)や空(null)のときの展開方法を指定できます。 デフォルト値を指定したり、エラーを発生させて終了させたりできます。
rm -rf ${appdir:?}/var/log
#誤って「/var/log」が削除されることを防げる
▼一致した文字列を削除するパラメータ展開
| パラメータ展開 | 説明 |
|---|---|
| ${parameter%word} | 最短一致した接尾辞のパターンを削除する |
| ${parameter%%word} | 最長一致した接尾辞のパターンを削除する |
| ${parameter:#word} | 最短一致した接頭辞のパターンを削除する |
| ${parameter:##word} | 最長一致した接頭辞のパターンを削除する |
上記の式を用いるとparameterに格納されている文字列から、wordを展開した文字列に一致した文字列を削除できます。wordを展開するときにはパターンマッチングが適用されます。
-
コマンド置換
- コマンドの実行結果を文字列として取得し、変数に代入したり他のコマンドの引数として渡したりする機能
$(command)の形式をコマンド置換と呼びます。
以下☟はコマンドの出力を変数dataに設定します。
data=$(cat data.txt)
注意
「'command'」の形式は非推奨です。
過去の互換のためのみに利用し、新たには利用しないでください。
-
算術展開
-$((expression))の形式のこと
-算術式を評価した値に置換する
#変数aとbの足し算の結果を出力
#!/bin/sh
a=1
b=2
echo $((a+b))
4. まとめ
今回は以下の6点について説明しました。
- パラメータと変数
- 引用
- パターンマッチング
- リダイレクトとパイプ
- シェルスクリプトの構成
- 展開
今回はSoftware Design 2024年12月号の雑誌を参考にシェルスクリプトの基礎についてまとめました。
雑誌が少し古いものになるので現在の仕様と完全に一致していない可能性があります。
一応動作検証は行っていますが、万が一古い記述や間違いが含まれていましたらご容赦ください。
5. 参考
この記事は以下の情報を参考にして執筆しました。
▼ubuntu
▼Software Design 2024年12月号