Skip to content

Instantly share code, notes, and snippets.

@momo-lab
Created May 15, 2012 10:31
Show Gist options
  • Save momo-lab/2700678 to your computer and use it in GitHub Desktop.
Save momo-lab/2700678 to your computer and use it in GitHub Desktop.
オプションの説明文(ヘルプ)内容から、オプションの解析を行うbash用スクリプト
#!/bin/bash
# コマンドの説明(ヘルプ)の文章をそれなりに解釈して、
# 引数のオプション解析を行うbash用関数
#
# 詳しくは後ろの方にある使用例を参照のこと。
function optparse() {
if [[ ! $optparse_prefix ]]; then
optparse_prefix="opt_"
fi
function parse_message() {
echo "$optparse_help_message" | awk '
function make_name(short, long) {
name = length(long) == 0 ? short : long;
gsub(/^--?/, "", name);
gsub(/-/, "_", name);
return name;
}
function parse(short, long, arg) {
# 長いパラメータに=を含むなら、それを引数とする
if (pos = match(long, /=/)) {
arg = "<" substr(long, pos + 1) ">";
long = substr(long, 1, pos - 1);
}
# 引数をとるかどうか
is_arg = match(arg, /^<.*>$/);
# 変数として出力
name = make_name(short, long);
print "optparse_args=(${optparse_args[@]} \"" name "|" short "|" long "|" is_arg "\")";
# getopt用の引数を生成
gsub(/^-/, "", short);
gsub(/^--/, "", long);
if (length(short) > 0) {
short_arg = short_arg short;
if (is_arg) short_arg = short_arg ":"
}
if (length(long) > 0) {
long_arg = long_arg "," long;
if (is_arg) long_arg = long_arg ":"
}
}
# 長短両方のパラメータ定義あり
/^[ \t]*-[^- ][, \t][ \t]*--[^ ]+/ {
gsub(/,$/, "", $1);
parse($1, $2, $3);
next;
}
# 短いパラメータ定義のみ
/^[ \t]*-[^- ][ \t]/ {
parse($1, "", $2);
next;
}
# 長いパラメータ定義のみ
/^[ \t]*--[^ ]+/ {
parse("", $1, $2);
next;
}
END {
print "optparse_short=" short_arg
print "optparse_long=" long_arg
}
' -
}
eval `parse_message`
args=`getopt -o +$optparse_short -l $optparse_long -- "$@"`
result=$?
if [[ $result != 0 ]]; then
echo "optparse_result=$result"
return $result
fi
eval set -- "$args"
until [[ "$1" == "--" ]]; do
for param in ${optparse_args[@]}; do
name=`echo $param | cut -d"|" -f1`
short=`echo $param | cut -d"|" -f2`
long=`echo $param | cut -d"|" -f3`
is_arg=`echo $param | cut -d"|" -f4`
if [[ "$1" == "$short" || "$1" == "$long" ]]; then
if [[ "$is_arg" == "1" ]]; then
echo "$optparse_prefix$name=\"$2\""
shift
else
echo "$optparse_prefix$name=1"
fi
break
fi
done
shift
done
shift
set_param=""
while [[ $1 ]]; do
set_param="$set_param \"$1\""
shift
done
echo "set -- $set_param"
echo "optparse_result=0"
return 0
}
# 以降は使用例
# 解析結果が代入される変数のプレフィクス
# 省略可能で、省略時は「opt_」となる
optparse_prefix="opt_"
# $optparse_help_message変数に、コマンドのヘルプ内容を記載する。
# サポート可能なパターンを以下に示している
optparse_help_message=$(cat << EOL
usage: $0 [options] ...
-a 短いオプション(on/off)
-b <param> 短いオプション(パラメータ指定有り)
--long-c 長いオプション(on/off)
--long-d <param> 長いオプション(パラメータ指定有り)
--long-e=param 長いオプション(パラメータ指定有り)
-f, --long-f 長短両方のオプション(on/off)
-g, --long-g <param> 長短両方のオプション(パラメータ指定有)
-h, --long-h=param 長短両方のオプション(パラメータ指定有)
EOL
)
# optparse関数に引数を渡し、結果の標準出力をevalにかけることで、
# 引数の解析結果を変数に代入する。
eval "$(optparse "$@")"
# 解析に成功したかどうかは、$optparse_result変数でハンドリング可能
if [[ $optparse_result != 0 ]]; then
echo "$optparse_help_message"
exit 1
fi
# 実際の解析結果は$optparse_prefix変数で定義した文字列で始まる変数に代入される。
# 長いオプションが定義されている場合は、長いオプション名(ハイフンはアンダースコアに変換)を
# 変数名とし、短いオプションの身が定義されている場合はそれを変数名とする。
echo "-a=$opt_a"
echo "-b=$opt_b"
echo "--long-c=$opt_long_c"
echo "--long-d=$opt_long_d"
echo "--long-e=$opt_long_e"
echo "-f,--long-f=$opt_long_f"
echo "-g,--long-g=$opt_long_g"
echo "-h,--long-h=$opt_long_h"
# 解析できた引数は、$@からは取り除かれている。
for i in `seq 1 $#`; do
echo "args[$i]=$1"
shift
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment