シェルスクリプトを読みやすくする工夫を紹介します

riddle
MIXI DEVELOPERS
Published in
6 min readJan 12, 2022

こんにちは ミクシィの 開発本部 SREグループ の riddle です。

※こちらで自己紹介を簡単にしていますのでよろしければご覧ください。
https://mixi-developers.mixi.co.jp/job-change-8c2a7d7c296a

色んな所で使うシェルスクリプトですが非常に便利な反面、他の言語に比べると癖が強く、IDEなどでも対応が少ないため読みづらいと思います。

シェルスクリプトが読みづらい人

今回は、そんなシェルスクリプトを書く上で個人的に実践しているいくつかのテクニックを紹介します!

※もっとこうするといいよ!というテクニックをご存知のかたは、ぜひ教えていただけると幸いです

· 1. コマンドオプションは配列を使う
· 2. pipe 中にコメントを挟む
· 3. heredoc の区切りは意味ある文字にする
· 4. 関数を使って処理をまとめる
· まとめ

1. コマンドオプションは配列を使う

例えばこんなコマンドがあるとします。見づらいですね。なんとなくオプションから意味が取れますが、なぜそのオプションが使われているかはわかりません。

$ curl --get --silent --http2 --location  -H "Content-Type: application/json" http://google.com

コメントを足してみます。(内容は適当です)

# google.com にアクセスし JSON 形式で結果を取得する
# 301 が帰ってくるので location を指定する
# 高速化のため http2 を使用する
$ curl --get --silent --http2 --location -H "Content-Type: application/json" http://google.com

少しわかりやすくなった気がします。ただ引数が増えてくるとひたすらコメントが長くなりますし、そもそもどのオプションの説明をしているのかわかりません。

ということでおすすめしたいのがこちらです。

$ curl_opt=(
--get
--silent
# 高速化のため http2 を使用する
--http2
# 301 が帰ってくるので location を指定する
--location
# JSON 形式で出力する
-H "Content-Type: application/json"
)
$ curl "${curl_opt[@]}" http://google.com

オプションを配列にまとめ、改行区切りにして定義することで1行に1つのオプションが定義でき、コメントを記載することもできます。

2. pipe 中にコメントを挟む

シェルスクリプトの pipe は非常に便利ですが、時々何をやっているのかがわからなくなるときがあります。このテクニックはそれを少し解消するものです。

こんなコマンドがあるとします。

grep aaa testfile | grep bbbb | sed 's/hoge//g' | awk '{print $2}' 

ちょっと整形して見やすくします。

grep aaa testfile   \
| grep bbbb \
| sed 's/hoge//g' \
| awk '{print $2}'

さらにこれにコメントを足してみます。

grep aaa testfile                   \
\
`# testfile 内の bbbb を抽出する` \
| grep bbbb \
\
`# hoge を削除する` \
| sed 's/hoge//g' \
\
`# 2行目のみ取得する` \
| awk '{print $2}'

バッククオート(`)で囲まれた範囲はコマンドとして認識されますが、先頭に(#) がついていればコメントとして扱われるのを利用して`# コメント`を付与しています。

3. heredoc の区切りは意味ある文字にする

EOF や EOT などが使われる事が多い heredoc ですが、実は結構なんでも使えます。(ためしてみたら * でもイケてビックリ)

cat <<*
aaa
*
aaa

ですので、なんのための heredoc なのかを明示するとよりわかりやすいですね。こんな感じです。

cat << MAIL_TEMPLATE > template.txt
タイトル: xxx
宛先: xxx
本文: xxx
MAIL_TEMPLATE

4. 関数を使って処理をまとめる

例えば、データを取得し、整形して、アップロードするというステップのスクリプトがあったとします。

# データを取得
...
...
...
...
...
# データを整形
...
...
...
...
...
# データをアップロード
...
...
...
...
...

このように処理の順に書いていくのが通常ですが、処理が増えたり、チェックしたい内容だったりが出てきたときに少し修正しづらいです。

そこで関数を用いてこのようにしてみます。

# データを取得する関数です(xxを引数にとりxxを行います)
function getData() {
...
...
...
...
...
}
# データを整形する関数です(xxを引数にとりxxを行います)
function formatData() {
...
...
...
...
...
}
# データをアップロードする関数です(xxを引数にとりxxを行います)
function uploadData() {
...
...
...
...
...
}
# 処理の実行
getData
formatData
uploadData

関数化により、各関数の役割が明確になりフローもわかりやすくなりました。また関数にしたことで関数単位にチェックやテストを追うことも出来ます。

まとめ

シェルスクリプトは簡単に書けて、手早く、様々なことができる便利なツールですが、こういった観点にも注意してスクリプトを作成してみるとより可読性が上がるかなと思います。

こんなテクニックもあるよ!があれば、ぜひコメントで教えていただけると嬉しいです!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Sign up for free

Membership

Access the best member-only stories.

Support independent authors.

Listen to audio narrations.

Read offline.

Join the Partner Program and earn for your writing.

Try for $5/month