もっと詳しく

こんにちは、山田ハヤオです。Alter Linuxのソースコードにはたくさんのシェルスクリプトがあります。

ほとんどの処理は「build.sh」というシェルスクリプトにかかれていますが、いくつかの処理は別のファイルに分割し、まるでコマンドのように引数をとって動作します。

そんな中で欠かせないのが引数解析です。

オブジェクト指向言語のように簡単に実装できればいいのですが、全てをコマンドとして扱うシェルスクリプトはそうはいきません。

引数解析はある程度決まったテンプレートを利用します。

(Linuxを前提にしています。BSD系だと互換性がありません。)

(それぞれのコマンドの基本的な説明は省略するので各自で調べてください。)

getoptを使う

C言語にもgetoptって関数?があって似たように使うらしい?ですね(不確かすぎる)

ARGUMENT="${@}"
opt_short="a:bh"
opt_long="aa:,bb,help"
OPT=$(getopt -o ${opt_short} -l ${opt_long} -- ${ARGUMENT})
[[ ${?} != 0 ]] && exit 1
eval set -- "${OPT}"
unset OPT opt_short opt_long
while true; do
    case "${1}" in
        -a | --aa)
            echo "${2}"
            shift 2
            ;;
        -b | --bb)
            echo "-bか--bbが選択されました"
            shift 1
            ;;
        -h | --help)
            echo "使い方: -a <引数> -b -h"
            exit 0
            ;;
        --)
            shift 1
            break
            ;;
    esac
done

1つづつ解説します。

getoptの仕事

getoptコマンドは引数を解析して並び替えてくれます。

例えば「-a」と「-b」というオプションを「-ab」と指定した場合、getoptはそれを分解してくれます。

getoptで引数を整頓することで解析がとても楽になります。

短いオプションの指定方法

先程のコードのopt_short変数で設定します。

文字をそのまま入れて、引数をとる場合は「:」をつけます。

「-x <引数>」「-t」「-z <引数>」という場合は「x:tz:」という感じです。

長いオプションの指定方法

opt_long変数で指定します。短い場合と違って,で区切ります。

「–aaa <引数>」「–help」「–fix」という場合は「aaa:,help,fix」といった具合です。

実際の処理の設定

case内に該当する処理を書くだけです。どうしてこれで動くのかは次に説明します。

上のコードの全体的な説明

まず、opt_shortとopt_longの情報をもとにgetoptが引数を整形します。

整形されたテキストはOPT変数に代入されます。

この段階で整形された引数の最後に「–」という文字列がはいります。これが重要です。

[[ ${?} != 0 ]] && exit 1は「getoptがエラーを出した場合はスクリプトを終了させる」という意味です。

その後、整形された引数を「コマンドラインで設定された引数」として上書きします。

これでユーザーが指定した引数ではなく、getoptで整形された引数が渡されたことになります。

この処理を行っているのがeval set -- "${OPT}"という部分です。

あとはwhileで無限ループを行います。

${1}変数には引数の1つ目の文字が代入されていますので、それをcaseでさばいていきます。

処理が終わったらcaseの最後でshiftコマンドで引数を削っていきます。

「-a」のような場合はshift 1、「-b <引数>」のような場合はshift 2です。

全ての処理をし終わると、最後に「–」という文字が残ります。先程getoptで加えた文字ですね。

この文字列がきたらbreakによって無限ループから抜け出します。

これで全てのオプションの解析と処理が終わりました。

最後に

正直文章で説明するのは難しいです。

上のテンプレートの先頭にset -xvとつけるとデバッグモードになります。

デバッグモードでは変数の値や実行されているコマンドの詳細がわかるので、それを使って実際の挙動を追ってみてください。

また、Alter Linuxのソースコードでは様々な部分で引数解析を行っているので参考にしてみてください。

 

 

おまけという名、Arch Linuxのどうでも良い雑学のクイズ

どんどんぱふぱふー … はい、山田ハヤオです。

何の言語もかけないくせにLinux歴だけは無駄に長いです。

ということで(?)あまり知られてないことをクイズにしようと思います。

問題のすぐ下に答えがあるとかいうアホ仕様なので目次使って問題見てみてください。

レッツゴー!

makepkgコマンドは何の言語で書かれてる?

A. シェルスクリプト mkinotcpioなどもシェルで書かれている。

PKGBUILDを扱う上でそのほうがよかったんでしょうか?

arch-chrootコマンドをUbuntuで使うにはどうしたらいい?

A. 普通にarch-install-scriptsパッケージをインストールすれば使えます()

名前に「arch」とかついておきながらDebianやFedoraなどでも普通に使えます。

Arch Linuxの公式リポジトリは誰が管理してる?

A. TUと呼ばれるすごい人たち。TUになるにはいろいろルールが合って面倒です。

AURで人気のパッケージを公式リポジトリに入れたりフォーラムを管理したりする偉い人です。

Manjaroとの違いは?

A. 何もかも違う。一緒なのはパッケージマネージャくらい。

パッケージの互換性はあるけどカーネルとかもいろいろ別物。

mhwdというツールが非常に優秀でドライバとかカーネルの管理をしっかりと全部やってくれる。

Arch Linuxの独自ツールは?

A. Ubuntuにはいろんな独自ツールが有りますが、Archの場合はarchlinux-javaくらい。

(pacmanとかパッケージマネージャは除く)

UbuntuとかDebianだとupdate-alternativeとかいろいろあります。

終わり

あんま知られてないことと言っておきながら有名なものばかりだったかもしれません()

他にもこんなのがあるよーという場合はコメントで教えてください。

おすすめブログ↓

https://blog.fascode.net/2021/02/28/make_shell_multi_lang_spt/

The post シェルスクリプトで引数解析をする方法 【Linux 豆知識】 first appeared on FascodeNetwork Blog.