一个不错的命令行解析类

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介:
原文链接:Command line parser



 作者所考虑的语法是:
 复制代码
CommandLine::=[<Key> [,<Key>]]
<Key>::=<Delimeter>KeyName[<Separator><Value>]
<Value> ::= { KeyValue | <QuoteChar>Quoted Key Value<QuoteChar>} ][
<Delimeter>::= { - | / }
<Separator>::= { : }
<QuoteChar>::= { " }

复制代码


复制代码

typedef CString CCmdLineParser_String ;

#include <map>
using std::map;


class CCmdLineParser 
{
public:
    class CValsMap : public map<CCmdLineParser_String, CCmdLineParser_String> {};//存储关键字--值对
    typedef CValsMap::const_iterator POSITION;//迭代器
public:
    CCmdLineParser(LPCTSTR sCmdLine = NULL, bool bCaseSensitive = false);//默认大小写不敏感
    virtual ~CCmdLineParser();

    bool Parse(LPCTSTR sCmdLine);//解析命令行

    LPCTSTR getCmdLine() const { return m_sCmdLine; }

    void setCaseSensitive(bool bSensitive) { m_bCaseSensitive = bSensitive; }
    bool getCaseSensitive() const { return m_bCaseSensitive; }

    const CValsMap& getVals() const { return m_ValsMap; }

    // Start iterating through keys and values
    POSITION getFirst() const;//第一个
    // Get next key-value pair, returns empty sKey if end reached
    POSITION getNext(POSITION& pos, CCmdLineParser_String& sKey, CCmdLineParser_String& sValue) const;//迭代器往后
    // just helper ;)
    bool isLast(POSITION& pos) const;//是否是最后一个

    // TRUE if "Key" present in command line
    bool HasKey(LPCTSTR sKey) const;//是否包含指定关键字
    // Is "key" present in command line and have some value
    bool HasVal(LPCTSTR sKey) const;//是否包含指定值
    // Returns value if value was found or NULL otherwise
    LPCTSTR GetVal(LPCTSTR sKey) const;//获取值
    // Returns true if value was found
    bool GetVal(LPCTSTR sKey, CCmdLineParser_String& sValue) const;

private:
    CValsMap::const_iterator findKey(LPCTSTR sKey) const;//查找指定关键字
private:
    CCmdLineParser_String m_sCmdLine;
    CValsMap    m_ValsMap;
    bool m_bCaseSensitive;

    static const TCHAR m_sDelimeters[];
    static const TCHAR m_sValueSep[];
    static const TCHAR m_sQuotes[];
};

复制代码

复制代码
const TCHAR CCmdLineParser::m_sDelimeters[] = _T("-/");//键的起始符
const TCHAR CCmdLineParser::m_sQuotes[] = _T("\"");    // Can be _T("\"\'"),  for instance
const TCHAR CCmdLineParser::m_sValueSep[] = _T(" :"); // Space MUST be in set 键值分隔符

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CCmdLineParser::CCmdLineParser(LPCTSTR sCmdLine, bool bCaseSensitive)
: m_bCaseSensitive(bCaseSensitive)
{
    if(sCmdLine) 
    {
        Parse(sCmdLine);
    }
}

CCmdLineParser::~CCmdLineParser()
{
    m_ValsMap.clear();
}

bool CCmdLineParser::Parse(LPCTSTR sCmdLine) 
{
    if(!sCmdLine) return false;
    
    m_sCmdLine = sCmdLine;
    m_ValsMap.clear();
    const CCmdLineParser_String sEmpty;

    int nArgs = 0;
    LPCTSTR sCurrent = sCmdLine;
    while(true) {
        // /Key:"arg"
        if(_tcslen(sCurrent) == 0) { break; } // No data left
        LPCTSTR sArg = _tcspbrk(sCurrent, m_sDelimeters);
        if(!sArg) break; // No delimeters found
        sArg =  _tcsinc(sArg);
        // Key:"arg"
        if(_tcslen(sArg) == 0) break; // String ends with delimeter
        LPCTSTR sVal = _tcspbrk(sArg, m_sValueSep);
        if(sVal == NULL) { //Key ends command line
            CCmdLineParser_String csKey(sArg);
            if(!m_bCaseSensitive) {
                csKey.MakeLower();
            }
            m_ValsMap.insert(CValsMap::value_type(csKey, sEmpty));
            break;
        } else if(sVal[0] == _T(' ') || _tcslen(sVal) == 1 ) { // Key with no value or cmdline ends with /Key:
            CCmdLineParser_String csKey(sArg, sVal - sArg);
            if(!csKey.IsEmpty()) { // Prevent /: case
                if(!m_bCaseSensitive) {
                    csKey.MakeLower();
                }
                m_ValsMap.insert(CValsMap::value_type(csKey, sEmpty));
            }
            sCurrent = _tcsinc(sVal);
            continue;
        } else { // Key with value
            CCmdLineParser_String csKey(sArg, sVal - sArg);
            if(!m_bCaseSensitive) {
                csKey.MakeLower();
            }

            sVal = _tcsinc(sVal);
            // "arg"
            LPCTSTR sQuote = _tcspbrk(sVal, m_sQuotes), sEndQuote(NULL);
            if(sQuote == sVal) { // Quoted String
                sQuote = _tcsinc(sVal);
                sEndQuote = _tcspbrk(sQuote, m_sQuotes);
            } else {
                sQuote = sVal;
                sEndQuote = _tcschr(sQuote, _T(' '));
            }

            if(sEndQuote == NULL) { // No end quotes or terminating space, take rest of string
                CCmdLineParser_String csVal(sQuote);
                if(!csKey.IsEmpty()) { // Prevent /:val case
                    m_ValsMap.insert(CValsMap::value_type(csKey, csVal));//保存
                }
                break;
            } else { // End quote or space present
                if(!csKey.IsEmpty()) {    // Prevent /:"val" case
                    CCmdLineParser_String csVal(sQuote, sEndQuote - sQuote);
                    m_ValsMap.insert(CValsMap::value_type(csKey, csVal));
                }
                sCurrent = _tcsinc(sEndQuote);
                continue;
            }
        }

    }
    
    return (nArgs > 0);
}

CCmdLineParser::CValsMap::const_iterator CCmdLineParser::findKey(LPCTSTR sKey) const 
{
    CCmdLineParser_String s(sKey);
    if(!m_bCaseSensitive) {
        s.MakeLower();
    }
    return m_ValsMap.find(s);
}
// TRUE if "Key" present in command line
bool CCmdLineParser::HasKey(LPCTSTR sKey) const 
{
    CValsMap::const_iterator it = findKey(sKey);
    if(it == m_ValsMap.end()) return false;
    return true;
}

// Is "key" present in command line and have some value
bool CCmdLineParser::HasVal(LPCTSTR sKey) const 
{
    CValsMap::const_iterator it = findKey(sKey);
    if(it == m_ValsMap.end()) return false;
    if(it->second.IsEmpty()) return false;
    return true;
}
// Returns value if value was found or NULL otherwise
LPCTSTR CCmdLineParser::GetVal(LPCTSTR sKey) const 
{
    CValsMap::const_iterator it = findKey(sKey);
    if(it == m_ValsMap.end()) return false;
    return LPCTSTR(it->second);
}
// Returns true if value was found
bool CCmdLineParser::GetVal(LPCTSTR sKey, CCmdLineParser_String& sValue) const 
{
    CValsMap::const_iterator it = findKey(sKey);
    if(it == m_ValsMap.end()) return false;
    sValue = it->second;
    return true;
}

CCmdLineParser::POSITION CCmdLineParser::getFirst() const 
{
    return m_ValsMap.begin();
}
CCmdLineParser::POSITION CCmdLineParser::getNext(POSITION& pos, CCmdLineParser_String& sKey, CCmdLineParser_String& sValue) const 
{
    if(isLast(pos)) {
        sKey.Empty();
        return pos;
    } else {
        sKey = pos->first;
        sValue = pos->second;
        pos ++;
        return pos;
    }
}
// just helper ;)
bool CCmdLineParser::isLast(POSITION& pos) const
{
    return (pos == m_ValsMap.end());
}


复制代码

复制代码
#include "stdafx.h"
#include "cmdlineparser.h"

int main(int argc, char* argv[])
{
    CCmdLineParser parser(_T("/Key1 /Key2: -Key3:Val3 -Key4:\"Val 4-with/spaces/and-delimeters\" /Key5:Val5"));

    ASSERT(parser.HasKey(_T("Key1")) == true);
    ASSERT(parser.HasKey(_T("Key10")) == false);
    ASSERT(parser.HasVal(_T("Key2")) == false);
    ASSERT(parser.HasKey(_T("Key5"))==true);
    _tprintf(_T("==================== Test Parser ====================\n"));
    _tprintf(_T("Command line: [%s]\n"), parser.getCmdLine());//获取命令行参数
    _tprintf(_T("Key1 has value: [%s]\n"), parser.GetVal(_T("Key1")));// -> []; //(empty string)
    _tprintf(_T("Key2 has value: [%s]\n"), parser.GetVal(_T("Key2")));// -> []; 
    _tprintf(_T("Key3 has value: [%s]\n"), parser.GetVal(_T("Key3")));// -> [Val3];
    _tprintf(_T("Key4 has value: [%s]\n"), parser.GetVal(_T("Key4")));// -> [Val 4-with/spaces/and-delimeters];
    _tprintf(_T("Key5 has value: [%s]\n"), parser.GetVal(_T("Key5")));// -> []; //(empty string)

    _tprintf(_T("\n================= Real Command Line =================\n"));
    CCmdLineParser realParser(::GetCommandLine());
    CCmdLineParser::POSITION pos = realParser.getFirst();    
    CString sKey, sVal;
    while(!realParser.isLast(pos)) 
    {
        realParser.getNext(pos, sKey, sVal);
        _tprintf(_T("Key: [%s], Val: [%s]\n"), sKey, sVal);
    }
    system("pause");
    return 0;
}

复制代码



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/06/28/1231628.html,如需转载请自行联系原作者
目录
相关文章
|
2月前
|
域名解析 网络协议 安全
在Linux中,想在命令行下访问某个网站,并且该网站域名还没有解析,如何做?
在Linux中,想在命令行下访问某个网站,并且该网站域名还没有解析,如何做?
|
11天前
|
Python
命令行解析工具 argparse
命令行解析工具 argparse
37 14
|
3天前
|
存储 编译器 数据安全/隐私保护
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解2
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
14 3
|
4天前
|
编译器 C++
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解1
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
22 3
|
4月前
|
缓存 开发者 索引
深入解析 `org.elasticsearch.action.search.SearchRequest` 类
深入解析 `org.elasticsearch.action.search.SearchRequest` 类
|
2月前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
29 0
Spring高手之路22——AOP切面类的封装与解析
|
2月前
|
JSON 图形学 数据格式
Json☀️ 一、认识Json是如何解析成类的
Json☀️ 一、认识Json是如何解析成类的
|
2月前
|
存储 Go UED
精通Go语言的命令行参数解析
【8月更文挑战第31天】
27 0
|
2月前
|
SQL 分布式计算 算法
【python】python指南(二):命令行参数解析器ArgumentParser
【python】python指南(二):命令行参数解析器ArgumentParser
31 0
|
2月前
|
Go
【go笔记】使用标准库flag解析命令行参数
【go笔记】使用标准库flag解析命令行参数

热门文章

最新文章

推荐镜像

更多