option=value
語法只需包含 argparse.hpp 就可以了。
# include < argparse/argparse.hpp >
若要開始解析命令列參數,請建立一個ArgumentParser
。
argparse::ArgumentParser program ( " program_name " );
注意: ArgumentParser
有一個可選的第二個參數,它是程式版本。範例: argparse::ArgumentParser program("libfoo", "1.9.0");
注意: ArgumentParser
有可選的第三個和第四個參數來控制預設參數。範例: 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。 定義標誌參數時,可以使用簡寫flag()
它與default_value(false).implicit_value(true)
相同。
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;
}
在某些情況下,您希望將可選參數設定為必需。如上所述,可選參數以-
或--
開頭。您可以將這些類型的參數設為必需,如下所示:
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)
傳回std::optional<T>
,而不是回傳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
您可能希望允許重複可選參數並將所有值收集到一處。
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` 將確保命令列上僅存在互斥組中的參數之一:
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()
函數也接受一個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
將不同數量的命令列參數與單一操作相關聯。當使用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
。這只適用於短的單字元參數名稱。-a
和-b
變成 true。-c
輸入。.default_value
定義的 {0.0, 0.0}對於輸入,使用者可以表達值的原始類型。
.scan<Shape, T>
方法嘗試將傳入的std::string
轉換為遵循Shape
轉換說明符的T
如果發生錯誤,則會引發std::invalid_argument
或std::range_error
例外。
program.add_argument( " -x " )
.scan< ' d ' , int >();
program.add_argument( " scale " )
.scan< ' g ' , double >();
Shape
指定輸入“看起來像什麼”,類型範本參數指定預先定義操作的傳回值。可接受的型別是浮點型(即float、double、long double)和整數型(即signed char、short、int、long、long long)。
語法遵循std::from_chars
,但不完全重複。例如,十六進位數字可以以0x
或0X
開頭,並且帶有前導零的數字可以作為八進位值處理。
形狀 | 解釋 |
---|---|
'a' 或 'A' | 十六進位浮點數 |
'e' 或 'E' | 科學計數法(浮點) |
'f' 或 'F' | 固定表示法(浮點) |
“g”或“G” | 一般形式(固定的或科學的) |
'd' | 小數 |
'我' | 基數 == 10 的std::from_chars 語法 |
'o' | 八進位(無符號) |
'你' | 十進制(無符號) |
“x”或“X” | 十六進位(無符號) |
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
的第四個參數 ( 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
收集剩餘參數的過程也可以很好地處理可選參數: