映画『氷菓』(2017)
見はじめたのはアニメの方なんですが、まだ2話なので、先に映画の方見た方がよいかなあと、迷ってます。映画のPV見てしまうと、どうしても見ないと気が済まなくなってしまいます。
getoptではショートオプション、ロングオプションを使ってみたので、getoptsでも、ロングオプションを使ってみたいと思います。
しかし、man bashを見ても、ロングオプションのことが書いてありません。仕方ないので、bashのソースコードを読んでみます。
まずは取得。
takk@deb9:~$ mkdir src takk@deb9:~$ cd src takk@deb9:~/src$ apt-get source bash
バージョンは、4.4です。
takk@deb9:~/src$ ls bash-4.4 bash_4.4-5.debian.tar.xz bash_4.4-5.dsc bash_4.4.orig.tar.xz takk@deb9:~/src$ cd bash-4.4 takk@deb9:~/src/bash-4.4$
さっそくgrep。大量に出るのでファイル一覧を眺めます。
takk@deb9:~/src/bash-4.4$ grep -rl getopts * AUTHORS CHANGES CWRU/changelog ChangeLog MANIFEST Makefile.in builtins/Makefile.in builtins/getopt.c ~省略~ tests/getopts10.sub tests/getopts.right tests/nameref.right variables.c takk@deb9:~/src/bash-4.4$
本当に大量に出てきたので間引きましょう。poやdocといったディレクトリは処理が入っていないはずなので、検索から除外します。
takk@deb9:~/src/bash-4.4$ grep -rl getopts * --exclude-dir={po,doc,tests,examples} AUTHORS CHANGES CWRU/changelog ChangeLog MANIFEST Makefile.in builtins/Makefile.in builtins/getopt.c builtins/common.h builtins/mkbuiltins.c builtins/getopts.def debian/changelog debian/bash-builtins.7 execute_cmd.c support/mkclone support/rlvers.sh variables.c takk@deb9:~/src/bash-4.4$
ヒットするファイル数が少なくなったところで、文字列のファイル内を検索。
takk@deb9:~/src/bash-4.4$ ^-rl^-r^ grep -r getopts * --exclude-dir={po,doc,tests,examples} AUTHORS:builtins/getopts.def Brian Fox, Chet Ramey CHANGES:eee. Bash now restores getopts' internal state between calls to getopts even if CHANGES:g. Fixed a bug that caused the getopts builtin to not return failure if an ~省略~ builtins/getopts.def:dogetopts (argc, argv) builtins/getopts.def: /* argv[0] is "getopts". */ builtins/getopts.def: getopts_unbind_variable ("OPTARG"); builtins/getopts.def: getopts_bind_variable (name, "?"); builtins/getopts.def: ret = getopts_bind_variable (name, "?"); builtins/getopts.def: getopts_unbind_variable ("OPTARG"); builtins/getopts.def: ret = getopts_bind_variable (name, ":"); builtins/getopts.def: ret = getopts_bind_variable (name, "?"); builtins/getopts.def: getopts_unbind_variable ("OPTARG"); builtins/getopts.def: return (getopts_bind_variable (name, strval)); builtins/getopts.def:/* The getopts builtin. Build an argv, and call dogetopts with it. */ builtins/getopts.def:getopts_builtin (list) ~省略~ takk@deb9:~/src/bash-4.4$
どうやらgetopts.defというファイルで、getoptsの処理を実施しているようです。しかし、このgetopts.defにロングオプションの処理が見つかりません。ということは、getoptsではロングオプションは使えないということになってしまいます。そう判断する前にちょっと気になることが。ファイルの拡張子がdefってこともあり、getoptsを使った時に、本当にこのgetopts.defの処理が走るのか、少々自信がありません。printfを追加して確認してみます。
175行目にHELLO表示を追加しました。
takk@deb9:~/src/bash-4.4$ cat -n builtins/getopts.def ~省略~ 162 static int 163 dogetopts (argc, argv) 164 int argc; 165 char **argv; 166 { 167 int ret, special_error, old_opterr, i, n; 168 char strval[2], numval[16]; 169 char *optstr; /* list of options */ 170 char *name; /* variable to get flag val */ 171 char *t; 172 173 if (argc < 3) 174 { 175 printf("HELLO\n"); 176 builtin_usage (); 177 return (EX_USAGE); 178 } ~省略~
printfを追加したらビルド。
takk@deb9:~/src/bash-4.4$ ./configure takk@deb9:~/src/bash-4.4$ make takk@deb9:~/src/bash-4.4$ ./bash
実行します。getoptsに適当に引数を与えます。
takk@deb9:~/src/bash-4.4$ getopts a HELLO getopts: usage: getopts optstring name [arg] takk@deb9:~/src/bash-4.4$
HELLOが表示されたので、getopts.defの処理が実行される、ということで間違いないようです。やはりロングオプションの処理はしてないってことですね。
さて、どうしたものか。
ロングオプションは、–から始まることを利用して、ショートオプション名が”-“である、という解釈で解析しても良いかもしれません。その場合は、値付きのオプションとするため、:(コロン)が必要になります。
例えばこんなスクリプトにします。
takk@deb9:~$ cat -n test.sh 1 #!/bin/bash 2 3 while getopts "abcde-:" ret $@ 4 do 5 echo -e $ret $OPTARG 6 done 7 takk@deb9:~$
実行すると、
takk@deb9:~$ ./test.sh -abcde --this_is_longoption a b c d e - this_is_longoption takk@deb9:~$
オプション”-“の値として、this_is_longoptionが取得できました。
ヘビーな使い方をしないのであれば、これで十分かも。
コメント