65.9K
CodeProject 正在变化。 阅读更多。
Home

命令行解析器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (34投票s)

2002年8月18日

2分钟阅读

viewsIcon

222419

downloadIcon

5377

一个直观且可扩展的命令行解析器类,可以处理多种命令行格式。

引言

从命令行获取参数列表是许多应用程序的常见任务。 然而,目前还没有标准解决方案(据我所知;)。所以我写了类 CCmdLineParser,它可以从命令行解析参数,如果它们是以下列形式输入的:

  • /Key 
  • /KeyWithValue:Value 
  • /KeyWithComplexValue:"Some really complex value of /KeyWithComplexValue"

当然,支持多个键、Unicode 和长(最多 32Kb)命令行。

此实现需要 MFC 或 ATL CString 类,或一些具有类似接口的克隆,以及 STL 类 map

用法

首先,你应该构建这个对象并调用 Parse 函数(从构造函数或
CCmdLineParser parser(::GetCommandLine());
CCmdLineParser parser;
parser.Parse(_T("/Key /Key2:Val /Key3:\"Complex-Value\" -Key4"));

然后,有两种处理结果的方法。你可以检查命令行中是否指定了某个特定的键

if(parser.HasKey(_T("Key")) {
	// Do some stuff
}
if(parser.HasKey(_T("Key2")) {
	LPCTSTR szKey2Value = parser.GetVal(_T("Key2"));
	// Do something with value of Key2
}

LPCTSTR szKey3Value = parser.GetVal(_T("Key3"));
if(szKey3Value) {
	// There was key "Key3" in input,  
} else {
	// No key "Key3" in input
}

LPCTSTR szKey4Value = parser.GetVal(_T("Key4"));
// Key4 was found in input, but since no value was specified, 
// szKey4Value points to empty string

另一种使用方法是枚举命令行中的所有键

CString sKey, sValue;

CCmdLineParser::POSITION pos = parser.getFirst();
while(!realParser.isLast(pos)) {
	realParser.getNext(pos, sKey, sValue);
	// Do something with current key and value
}

定制和 "它是如何工作的"

重复的键

如果使用相同的键指定了几个不同的值,则仅存储第一个值。 因此,如果用户传递命令行 /Add:One /Add:Two/Add:Two 将被忽略,并且不会添加到解析列表中。

区分大小写/不区分大小写

默认情况下,键是区分大小写的。因此,/KeyOne 等于 -keyONE。这是通过在存储之前将所有键转换为小写来完成的。 如果您想更改此行为,请调用 setCaseSensitive(true) 或使用第二个参数设置为 true 的构造函数
CCmdLineParser parser(::GetCommandLine(), true);
这将切换解析器到区分大小写模式,如果用户传递 -key,那么 GetKey(_T("Key")) 将返回 false

语法

形式上,命令行应采用以下形式
CommandLine::=[<Key> [,<Key>...]]
<Key>::=<Delimeter>KeyName[<Separator><Value>]
<Value> ::= { KeyValue | <QuoteChar>Quoted Key Value<QuoteChar>} ][
<Delimeter>::= { - | / }
<Separator>::= { : }
<QuoteChar>::= { " }

<Delimeter><Separator><QuoteChar> 的值分别存储在静态变量 m_sDelimetersm_sValueSepm_sQuotes 中。 如果您想更改它们(例如,允许用户使用撇号指定带引号的值),您可以在 CmdLineParser.cpp 的开头执行此操作

const TCHAR CCmdLineParser::m_sQuotes[] = _T("\"\'");
注意:如果您想更改 m_sDelimeters,空格必须是此字符串的第一个字符。 此外,如果您有自己的 CString 类,其名称与 CString 不同,您可以在 CmdLineParser.h 的开头进行更改
typedef MyOwnCString CCmdLineParser_String;
就是这样! ;)
© . All rights reserved.