解析命令行选项
Introduction
ParseOptions
类负责解析通过 argc 和 argv 传递给main()的命令行选项。首先我们给出一个从命令行调用 Kaldi 程序的例子:
gmm-align --transition-scale=10.0 --beam=75 \
exp/mono/tree exp/mono/30.mdl data/L.fst \
'ark:add-deltas --print-args=false scp:data/train.scp ark:- |' \
ark:data/train.tra ark:exp/tri/0.ali
命令行选项只有长形式(没有单字符选项),必须出现在位置参数前面。在这里例子里有六个位置参数,从“exp/mono/tree”开始;注意以“ark:add-delta”开头的是一个带空格的单个字符串;单引号里的内容会被 shell 解释;这个参数作为管道被调用。
Example of parsing command-line options
我们解释下这些选项是如何被 C++ 处理的,下面是 gmm-align.cc
中的部分代码(为了表达更清晰,略微改动了下):
int main(int argc, char *argv[])
{
try { // try-catch block is standard and relates to handling of errors.
using namespace kaldi;
const char *usage =
"Align features given [GMM-based] models.\n"
"Usage: align-gmm [options] tree-in model-in lexicon-fst-in feature-rspecifier "
"transcriptions-rspecifier alignments-wspecifier\n";
// Initialize the ParseOptions object with the usage string.
ParseOptions po(usage);
// Declare options and set default values.
bool binary = false;
BaseFloat beam = 200.0;
// Below is a structure containing options; its initializer sets defaults.
TrainingGraphCompilerOptions gopts;
// Register the options with the ParseOptions object.
po.Register("binary", &binary, "Write output in binary mode");
po.Register("beam", &beam, "Decoding beam");
gopts.Register(&po);
// The command-line options get parsed here.
po.Read(argc, argv);
// Check that there are a valid number of positional arguments.
if(po.NumArgs() != 6) {
po.PrintUsage();
exit(1);
}
// The positional arguments get read here (they can only be obtained
// from ParseOptions as strings).
std::string tree_in_filename = po.GetArg(1);
...
std::string alignment_wspecifier = po.GetArg(6);
...
} catch(const std::exception& e) {
std::cerr << e.what();
return -1;
}
}
读上面的代码基本就明白它的功能。在通常的 Kaldi 程序中,处理流程是这样的:
- 用包含使用说明的字符串初始化
ParseOptions
对象 - 声明并给出可选参数(选项结构(options structure))的初始值
- 用
ParseOptions
对象注册命令行选项(选项结构有它们自己的注册函数,执行同样的功能) - 执行 “po.Read(argc, argv);”[如果存在无效选项,此处会退出程序]
- 检查
po.NumArgs()
在有效范围内 - 利用
po.GetArg(1)
等获取位置参数;对可能超出有效数目范围的可选位置参数来说,可用po.GetOptArg(n)
来获取第n个参数,如果n超出范围则返回空字符串
一般来说,在 Kaldi 程序中写一个新命令行时,最简单的方法就是拷贝一个现成的然后修改它。
Implicit command-line arguments
特定的命令行选项会被 ParseOptions
对象自动注册。这些包括:
-config
这个选项会从配置文件中导入命令行选项。e.g.如果我们设定-config=configs/my.conf
,my.conf
文件可能包含:--first-option=15 # This is the first option --second-option=false # This is the second option
-print-args
这个布尔型选项控制程序是否将命令行参数打印到标准错误流(默认是真);-print-args=false
会将它关掉-help
这个布尔型参数,如果是真,程序会打印出使用说明(像其他布尔型参数一样,只用-help
就认为是真)。一般你不输入任何命令行参数时就可以获得使用说明,因为大部分程序都需要有位置参数。-verbose
它控制冗余度,进而决定用 KALDI_VLOG 输出的日志信息是否被打印。值越大打印的信息越多(e.g.典型值是-verbose=2
)