option=value
構文の使用argparse.hpp をインクルードするだけで準備完了です。
# include < argparse/argparse.hpp >
コマンドライン引数の解析を開始するには、 ArgumentParser
作成します。
argparse::ArgumentParser program ( " program_name " );
注: ArgumentParser
にはオプションの 2 番目の引数があり、これはプログラムのバージョンです。例: argparse::ArgumentParser program("libfoo", "1.9.0");
注: ArgumentParser
には、デフォルトの引数を制御するオプションの 3 番目と 4 番目の引数があります。例: argparse::ArgumentParser program("libfoo", "1.9.0", default_arguments::help, false);
以下の「デフォルトの引数」を参照してください。
新しい引数を追加するには、 .add_argument(...)
を呼び出すだけです。 -v
や--verbose
など、グループ化する引数名の可変長リストを指定できます。
program.add_argument( " foo " );
program.add_argument( " -v " , " --verbose " ); // parameter packing
Argparse は、位置引数、オプション引数、複合引数など、さまざまな引数タイプをサポートしています。以下に、これらの各タイプを構成する方法を示します。
位置引数の例を次に示します。
# include < argparse/argparse.hpp >
int main ( int argc, char *argv[]) {
argparse::ArgumentParser program ( " program_name " );
program. add_argument ( " square " )
. help ( " display the square of a given integer " )
. scan < ' i ' , int >();
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
return 1 ;
}
auto input = program. get < int >( " square " );
std::cout << (input * input) << std::endl;
return 0 ;
}
そしてコードを実行します:
foo@bar:/home/dev/ $ ./main 15
225
何が起こっているかは次のとおりです。
add_argument()
メソッドは、プログラムが受け入れるコマンドライン オプションを指定するために使用されます。この場合、機能に合わせて「square」という名前を付けました。.scan
メソッドを使用してユーザー入力を整数に変換します。parser.get<T>(key)
メソッドを使用して、指定された引数に対してパーサーによって保存された値を取得できます。次に、オプションの引数を見てみましょう。オプションの引数は、 -
または--
で始まります ( --verbose
または-a
など)。オプションの引数は、入力シーケンスのどこにでも配置できます。
argparse::ArgumentParser program ( " test " );
program.add_argument( " --verbose " )
.help( " increase output verbosity " )
.default_value( false )
.implicit_value( true );
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
if (program[ " --verbose " ] == true ) {
std::cout << " Verbosity enabled " << std::endl;
}
foo@bar:/home/dev/ $ ./main --verbose
Verbosity enabled
何が起こっているかは次のとおりです。
--verbose
を指定せずにプログラムを実行してもエラーはスローされません。 .default_value(false)
を使用すると、オプションの引数が使用されない場合、その値は自動的に false に設定されることに注意してください。.implicit_value(true)
使用することにより、ユーザーは、このオプションが値を必要とするものではなくフラグであることを指定します。ユーザーが --verbose オプションを指定すると、その値は true に設定されます。 フラグ引数を定義するときは、 default_value(false).implicit_value(true)
と同じ短縮表現のflag()
を使用できます。
argparse::ArgumentParser program ( " test " );
program.add_argument( " --verbose " )
.help( " increase output verbosity " )
.flag();
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
if (program[ " --verbose " ] == true ) {
std::cout << " Verbosity enabled " << std::endl;
}
オプションの引数をrequired にしたいシナリオがあります。上で説明したように、オプションの引数は-
または--
で始まります。次のように、これらのタイプの引数を必須にすることができます。
program.add_argument( " -o " , " --output " )
.required()
.help( " specify the output file. " );
ユーザーがこのパラメータの値を指定しない場合、例外がスローされます。
あるいは、次のようにデフォルト値を指定することもできます。
program.add_argument( " -o " , " --output " )
.default_value(std::string( " - " ))
.required()
.help( " specify the output file. " );
オプションの引数が必要であるが、その引数に適切なデフォルト値がない場合は、次のようにテストと引数へのアクセスを組み合わせることができます。
if ( auto fn = program.present( " -o " )) {
do_something_with (*fn);
}
get
と同様に、 present
メソッドはテンプレート引数も受け入れます。ただし、 parser.present<T>(key)
T
を返すのではなくstd::optional<T>
を返すため、ユーザーがこのパラメーターに値を指定しない場合、戻り値はstd::nullopt
と同等になります。
ユーザーが.default_value
を持つ引数の値を指定したかどうかを知りたい場合は、引数.is_used()
かどうかを確認します。
program.add_argument( " --color " )
.default_value(std::string{ " orange " }) // might otherwise be type const char* leading to an error when trying program.get<std::string>
.help( " specify the cat's fur color " );
try {
program. parse_args (argc, argv); // Example: ./main --color orange
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
auto color = program.get<std::string>( " --color " ); // "orange"
auto explicit_color = program.is_used( " --color " ); // true, user provided orange
オプションの引数を繰り返して、すべての値を 1 か所に集めたい場合があります。
program.add_argument( " --color " )
.default_value<std::vector<std::string>>({ " orange " })
.append()
.help( " specify the cat's fur color " );
try {
program. parse_args (argc, argv); // Example: ./main --color red --color green --color blue
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
auto colors = program.get<std::vector<std::string>>( " --color " ); // {"red", "green", "blue"}
.default_value
には、 .get
型に一致する明示的なテンプレート パラメーターが指定されていることに注意してください。
一般的なパターンは、より大きな値を示すために引数を繰り返すことです。
int verbosity = 0 ;
program.add_argument( " -V " , " --verbose " )
.action([&]( const auto &) { ++verbosity; })
.append()
.default_value( false )
.implicit_value( true )
.nargs( 0 );
program.parse_args(argc, argv); // Example: ./main -VVVV
std::cout << " verbose level: " << verbosity << std::endl; // verbose level: 4
program.add_mutually_exclusive_group(required = false)
を使用して、相互排他的なグループを作成します。 `argparse` は、相互に排他的なグループ内の引数のうち 1 つだけがコマンドラインに存在することを確認します。
auto &group = program.add_mutually_exclusive_group();
group.add_argument( " --first " );
group.add_argument( " --second " );
次のような使用法ではエラーが発生します。
foo@bar:/home/dev/ $ ./main --first 1 --second 2
Argument '--second VAR' not allowed with '--first VAR'
add_mutually_exclusive_group()
関数は、相互に排他的な引数の少なくとも 1 つが必要であることを示すrequired
引数も受け入れます。
auto &group = program.add_mutually_exclusive_group( true );
group.add_argument( " --first " );
group.add_argument( " --second " );
次のような使用法ではエラーが発生します。
foo@bar:/home/dev/ $ ./main
One of the arguments '--first VAR' or '--second VAR' is required
明示的にprogram.get<T>(arg_name)
またはprogram[arg_name]
を呼び出す代わりに、引数をその値を格納する変数にバインドすることができます。
これは現在、 bool
型 (これは暗黙的にflag()
も呼び出します)、 int
、 double
、 std::string
、 std::vector<std::string>
およびstd::vector<int>
型の変数に対して実装されています。コマンドラインで引数が指定されていない場合は、デフォルト値 (設定されている場合) が変数に設定されます。
bool flagvar = false ;
program.add_argument( " --flagvar " ).store_into(flagvar);
int intvar = 0 ;
program.add_argument( " --intvar " ).store_into(intvar);
double doublevar = 0 ;
program.add_argument( " --doublevar " ).store_into(doublevar);
std::string strvar;
program.add_argument( " --strvar " ).store_into(strvar);
std::vector<std::string> strvar_repeated;
program.add_argument( " --strvar-repeated " ).append().store_into(strvar_repeated);
std::vector<std::string> strvar_multi_valued;
program.add_argument( " --strvar-multi-valued " ).nargs( 2 ).store_into(strvar_multi_valued);
std::vector< int > intvar_repeated;
program.add_argument( " --intvar-repeated " ).append().store_into(intvar_repeated);
std::vector< int > intvar_multi_valued;
program.add_argument( " --intvar-multi-valued " ).nargs( 2 ).store_into(intvar_multi_valued);
オプションの引数は-
で始まります。 argparse
負の数を扱えますか?答えは「はい」です!
argparse::ArgumentParser program;
program.add_argument( " integer " )
.help( " Input number " )
.scan< ' i ' , int >();
program.add_argument( " floats " )
.help( " Vector of floats " )
.nargs( 4 )
.scan< ' g ' , float >();
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
// Some code to print arguments
foo@bar:/home/dev/ $ ./main -5 -1.1 -3.1415 -3.1e2 -4.51329E3
integer : -5
floats : -1.1 -3.1415 -310 -4513.29
ここでわかるように、 argparse
負の整数、負の浮動小数点数、科学的表記法をサポートしています。
argparse::ArgumentParser program ( " main " );
program.add_argument( " square " )
.help( " display the square of a given number " )
.scan< ' i ' , int >();
program.add_argument( " --verbose " )
.default_value( false )
.implicit_value( true );
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
int input = program.get< int >( " square " );
if (program[ " --verbose " ] == true ) {
std::cout << " The square of " << input << " is " << (input * input) << std::endl;
}
else {
std::cout << (input * input) << std::endl;
}
foo@bar:/home/dev/ $ ./main 4
16
foo@bar:/home/dev/ $ ./main 4 --verbose
The square of 4 is 16
foo@bar:/home/dev/ $ ./main --verbose 4
The square of 4 is 16
std::cout << program
プログラムの使用法やArgumentParser
に登録された引数に関する情報を含むヘルプ メッセージを出力します。前の例のデフォルトのヘルプ メッセージは次のとおりです。
foo@bar:/home/dev/$ ./main --help
Usage: main [-h] [--verbose] square
Positional arguments:
square display the square of a given number
Optional arguments:
-h, --help shows help message and exits
-v, --version prints version information and exits
--verbose
また、 program.help().str()
を介して文字列でヘルプ メッセージを取得することもできます。
ArgumentParser::add_description
詳細な引数情報の前にテキストを追加します。 ArgumentParser::add_epilog
他のすべてのヘルプ出力の後にテキストを追加します。
# include < argparse/argparse.hpp >
int main ( int argc, char *argv[]) {
argparse::ArgumentParser program ( " main " );
program. add_argument ( " thing " ). help ( " Thing to use. " ). metavar ( " THING " );
program. add_argument ( " --member " ). help ( " The alias for the member to pass to. " ). metavar ( " ALIAS " );
program. add_argument ( " --verbose " ). default_value ( false ). implicit_value ( true );
program. add_description ( " Forward a thing to the next member. " );
program. add_epilog ( " Possible things include betingalw, chiz, and res. " );
program. parse_args (argc, argv);
std::cout << program << std::endl;
}
Usage: main [-h] [--member ALIAS] [--verbose] THING
Forward a thing to the next member.
Positional arguments:
THING Thing to use.
Optional arguments:
-h, --help shows help message and exits
-v, --version prints version information and exits
--member ALIAS The alias for the member to pass to.
--verbose
Possible things include betingalw, chiz, and res.
ArgumentParser オブジェクトは通常、単一のコマンドライン引数を実行する単一のアクションに関連付けます。 .nargs
異なる数のコマンドライン引数を 1 つのアクションに関連付けます。 nargs(N)
使用すると、コマンドラインからの N 個の引数がリストにまとめられます。
argparse::ArgumentParser program ( " main " );
program.add_argument( " --input_files " )
.help( " The list of input files " )
.nargs( 2 );
try {
program. parse_args (argc, argv); // Example: ./main --input_files config.yml System.xml
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
auto files = program.get<std::vector<std::string>>( " --input_files " ); // {"config.yml", "System.xml"}
ArgumentParser.get<T>()
はstd::vector
とstd::list
の特殊化があります。したがって、次のバリアント.get<std::list>
も機能します。
auto files = program.get<std::list<std::string>>( " --input_files " ); // {"config.yml", "System.xml"}
.scan
使用すると、コマンド ライン引数から必要な値の型のリストをすばやく作成できます。以下に例を示します。
argparse::ArgumentParser program ( " main " );
program.add_argument( " --query_point " )
.help( " 3D query point " )
.nargs( 3 )
.default_value(std::vector< double >{ 0.0 , 0.0 , 0.0 })
.scan< ' g ' , double >();
try {
program. parse_args (argc, argv); // Example: ./main --query_point 3.5 4.7 9.2
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
auto query_point = program.get<std::vector< double >>( " --query_point " ); // {3.5, 4.7, 9.2}
.nargs
を使用して引数の可変長リストを作成することもできます。以下にいくつかの例を示します。
program.add_argument( " --input_files " )
.nargs( 1 , 3 ); // This accepts 1 to 3 arguments.
Python の argparse の「?」、「*」、「+」など、いくつかの便利なパターンが定義されています。
program.add_argument( " --input_files " )
.nargs(argparse::nargs_pattern::any); // "*" in Python. This accepts any number of arguments including 0.
program.add_argument( " --input_files " )
.nargs(argparse::nargs_pattern::at_least_one); // "+" in Python. This accepts one or more number of arguments.
program.add_argument( " --input_files " )
.nargs(argparse::nargs_pattern::optional); // "?" in Python. This accepts an argument optionally.
複合引数は、結合されて単一の引数として提供されるオプションの引数です。例: ps -aux
argparse::ArgumentParser program ( " test " );
program.add_argument( " -a " )
.default_value( false )
.implicit_value( true );
program.add_argument( " -b " )
.default_value( false )
.implicit_value( true );
program.add_argument( " -c " )
.nargs( 2 )
.default_value(std::vector< float >{ 0 . 0f , 0 . 0f })
.scan< ' g ' , float >();
try {
program. parse_args (argc, argv); // Example: ./main -abc 1.95 2.47
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
auto a = program.get< bool >( " -a " ); // true
auto b = program.get< bool >( " -b " ); // true
auto c = program.get<std::vector< float >>( " -c " ); // {1.95, 2.47}
// / Some code that prints parsed arguments
foo@bar:/home/dev/ $ ./main -ac 3.14 2.718
a = true
b = false
c = {3.14, 2.718}
foo@bar:/home/dev/ $ ./main -cb
a = false
b = true
c = {0.0, 0.0}
何が起こっているかは次のとおりです。
-a
、 -b
、 -c
があります。-a
と-b
トグル引数です。-c
コマンドラインから 2 つの浮動小数点数が必要です。-abc
、 -bac
、 -cab
などの複合引数を処理できます。これは、短い 1 文字の引数名でのみ機能します。-a
と-b
true になります。-c
にマップされた入力を識別します。.default_value
で定義されているデフォルトの {0.0, 0.0} になります。入力の場合、ユーザーは値のプリミティブ型を表現できます。
.scan<Shape, T>
メソッドは、 Shape
変換指定子に続いて、受信std::string
T
に変換しようとします。エラーの場合はstd::invalid_argument
またはstd::range_error
例外がスローされます。
program.add_argument( " -x " )
.scan< ' d ' , int >();
program.add_argument( " scale " )
.scan< ' g ' , double >();
Shape
入力の「見た目」を指定し、type template 引数は事前定義されたアクションの戻り値を指定します。受け入れ可能な型は、浮動小数点 (つまり、float、double、long double) と整数 (つまり、signed char、short、int、long、long long) です。
文法はstd::from_chars
に従いますが、正確に複製するわけではありません。たとえば、16 進数は0x
または0X
で始まる場合があり、先頭にゼロがある数値は 8 進数値として扱われる場合があります。
形 | 解釈 |
---|---|
「a」または「A」 | 16進浮動小数点 |
「e」または「E」 | 科学表記法 (浮動小数点) |
「f」または「F」 | 固定記法(浮動小数点) |
「g」または「G」 | 一般的な形式 (固定形式または科学形式) |
「だ」 | 10進数 |
'私' | std::from_chars 文法 (base == 10) |
「お」 | 8 進数 (符号なし) |
「う」 | 10 進数 (符号なし) |
「x」または「X」 | 16 進数 (符号なし) |
argparse
-h
/ --help
および-v
/ --version
の事前定義された引数とアクションを提供します。デフォルトでは、これらのアクションはそれぞれヘルプまたはバージョン メッセージを表示した後にプログラムを終了します。この出口はデストラクターを呼び出しず、取得されたリソースのクリーンアップをスキップします。
これらのデフォルト引数は、 ArgumentParser
作成中に無効にできるため、これらの引数を独自の方法で処理できます。 (デフォルトの引数を選択する場合は、プログラム名とバージョンを含める必要があることに注意してください。)
argparse::ArgumentParser program ( " test " , " 1.0 " , default_arguments::none);
program.add_argument( " -h " , " --help " )
.action([=]( const std::string& s) {
std::cout << help (). str ();
})
.default_value( false )
.help( " shows help message " )
.implicit_value( true )
.nargs( 0 );
上記のコード スニペットはヘルプ メッセージを出力し、実行を継続します。 --version
引数はサポートされていません。
含まれる引数のデフォルトはdefault_arguments::all
です。 default_arguments::none
を使用すると、デフォルトの引数は追加されません。 default_arguments::help
とdefault_arguments::version
--help
と--version
を個別に追加します。
デフォルトの引数は、これらの引数でデフォルトの終了を無効にするときに使用できます。 ArgumentParser
へのこの 4 番目の引数 ( exit_on_default_arguments
) は、デフォルトのtrue値を持つ bool フラグです。次の呼び出しでは--help
と--version
が保持されますが、これらの引数が使用されている場合は終了しません。
argparse::ArgumentParser program ( " test " , " 1.0 " , default_arguments::all, false )
argparse
、コンパイラで使用するために、コマンドの最後に「残りの」引数を収集することをサポートしています。
foo@bar:/home/dev/ $ compiler file1 file2 file3
これを有効にするには、引数を作成し、それをremaining
としてマークするだけです。 argparse に渡される残りの引数はすべてここに集められます。
argparse::ArgumentParser program ( " compiler " );
program.add_argument( " files " )
.remaining();
try {
program. parse_args (argc, argv);
}
catch ( const std:: exception & err) {
std::cerr << err. what () << std::endl;
std::cerr << program;
std::exit ( 1 );
}
try {
auto files = program. get <std::vector<std::string>>( " files " );
std::cout << files. size () << " files provided " << std::endl;
for ( auto & file : files)
std::cout << file << std::endl;
} catch (std::logic_error& e) {
std::cout << " No files provided " << std::endl;
}
引数が指定されていない場合:
foo@bar:/home/dev/ $ ./compiler
No files provided
複数の引数が指定された場合:
foo@bar:/home/dev/ $ ./compiler foo.txt bar.txt baz.txt
3 files provided
foo.txt
bar.txt
baz.txt
残りの引数を収集するプロセスは、オプションの引数ともうまく連携します。