getopts - Rust
起動時引数の解析用crate。公式が提供している。
Pythonのargparseと同じような使用感。
主にOptionsとMatchesの2つのオブジェクトが提供される。
Optionsオブジェクトにパースしたいキーワードとその解析方法を次々設定して、最後に Options.parse()
で解析する。
返値のオブジェクトであるMatchesから、必要な情報を取得する。
単純な機能は過不足ない。「2つの内いずれかは必須」など複雑なことは出来ない。
解析できる構文
位置引数、キーワード引数、フラグ引数に対応(この名称は勝手に付けた)。キーワード引数とフラグ引数は、まとめて「オプション引数」と呼ばれることが多いかも。オプション引数の名前(ハイフンに続く文字)は自由に、「ハイフン1つ+1文字」の省略形と「ハイフン2つ+任意の文字数」のロング名とを設定できる。
> command AAA BBB -s CCC --longname DDD -e --flag AAA BBB が位置引数 -s CCC --longname DDD がキーワード引数(値を伴うオプション引数) -e --flag がフラグ引数(値を伴わないオプション引数)
位置引数
- 何番目の引数かによって指定
- キーワード引数とフラグ引数以外の引数を先頭から順に取得
- 「最初の位置引数が現れたら、後はハイフン付いていようと全て位置引数」と解釈するオプションが存在
キーワード引数
ハイフンから始まる所定のキーワードに続けて指定。
○: -o XXX or -oXXX or --opt XXX ×: -o=XXX or --opt=XXX
可変長引数は未対応だが、同じキーワードで複数回指定されたのを配列として受け取ることはできる。
×: -o XXX YYY ZZZ ○: -o XXX -o YYY -o ZZZ
- 「
-a
と-b
を同時に指定することは出来ない」「-a
を指定したら-b
も指定しないといけない」などは未対応 - 指定されなかった場合のデフォルト値を指定可能
FromStr
traitを実装している型なら、パースして返すよう指定することが可能
フラグ引数
-f
–flag
など単独でフラグとして指定。booleanで取得。
その他の機能
- ヘルプ用文字列の自動生成可
もっと複雑な構文が必要なら
Sample
extern crate getopts; use getopts::Options; use std::process; // 引数を格納する構造体 #[derive(Debug)] pub struct Args { repeat: usize, input: Vec<String>, output: String, } fn print_usage(exe_name: &str, opts: &Options) { let brief = format!("Usage: {} REPEAT [Options]", exe_name); print!("{}", opts.usage(&brief)); process::exit(0); } pub fn parameters() -> Args { // コマンドラインオプションを取得 let args: Vec<String> = std::env::args().collect(); // キーワード引数を指定 let mut opts = Options::new(); opts.optmulti("i", "", "set input file names", "NAME"); opts.optopt("o", "", "set output file name", "NAME"); opts.optflag("h", "help", "print this help"); // パース let matches = opts.parse(&args[1..]) .unwrap_or_else(|f| panic!(f.to_string())); // "h" が存在したらヘルプを表示して終了 if matches.opt_present("h") { print_usage(&args[0], &opts); } // 必要な位置引数がなかったらヘルプを表示して終了 if matches.free.is_empty() { print_usage(&args[0], &opts); } // キーワード引数の取得 let input = matches.opt_strs("i"); let output = matches.opt_str("o").unwrap_or("Default Value".to_string()); // 位置引数の取得 let repeat = matches.free[0].clone().parse::<usize>() .unwrap_or_else(|f| panic!(f.to_string())); // 構造体の生成 let ret = Args { repeat, input, output, }; return ret; } fn main() { let args = parameters(); println!("{:?}", args); }