映画『氷菓』(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が取得できました。
ヘビーな使い方をしないのであれば、これで十分かも。



コメント