使用std :: tr1 :: regex使用冒号进行Tokenize

时间:2013-01-12 03:05:07

标签: regex tr1

我正在开发一个准SCPI命令解析器,我想基于冒号拆分一个字符串,忽略引用的字符串。如果冒号之间没有文本,我想得到一个空字符串。

如果我在EditPad Pro 7.2.2中使用这个正则表达式,它确实完全我想要的。 (([^:\ “'] | \ ”[^ \“]的 \” | '[^'] ')+)

例如,使用此数据字符串: :FOO :::栏:巴兹

我得到6次点击:[空],foo,[空],[空],bar,baz

到目前为止,这么好。但是,在我的代码中,使用std :: tr1 :: regex,我使用相同的数据字符串获得 9 命中。 似乎就像我在每次非空击中后得到额外的空击。

void RICommandState::InitRawCommandEnum(const std::string& full_command)
{
    // Split string by colons, but ignore text within quotes.
    static const std::tr1::regex split_by_colon("(([^:\"']|\"[^\"]*\"|'[^']*')+)?");

    raw_command_list.clear();
    raw_command_index = 0;

    DebugPrintf(ZONE_REMOTE, (TEXT("InitRawCommandEnum FULL '%S'"), full_command.c_str()));

    const std::tr1::sregex_token_iterator end;
    for (std::tr1::sregex_token_iterator it(full_command.begin(),
                                            full_command.end(),
                                            split_by_colon);
         it != end;
         it++)
    {
        raw_command_list.push_back(*it);
        const std::string temp(*it);
        DebugPrintf(ZONE_REMOTE, (TEXT("InitRawCommandEnum '%S'"), temp.c_str()));
    }

    DebugPrintf(ZONE_REMOTE, (TEXT("InitRawCommandEnum hits = %d"), raw_command_list.size()));
}

这是我的输出:

InitRawCommandEnum FULL ':foo:::bar:baz'
InitRawCommandEnum ''
InitRawCommandEnum 'foo'
InitRawCommandEnum ''
InitRawCommandEnum ''
InitRawCommandEnum ''
InitRawCommandEnum 'bar'
InitRawCommandEnum ''
InitRawCommandEnum 'baz'
InitRawCommandEnum ''
InitRawCommandEnum hits = 9

最重要的问题是如何让我的正则表达式搜索为冒号分隔的每个标记产生一个(并且只有一个)命中?我的搜索表达式有问题吗?

或许我误解了结果?非空字符串后的空字符串是否具有特殊含义?如果是这样,什么?如果是这样的话,那么正确的解决方案就是忽略它们吗?

作为一个附带问题,我很好奇为什么我的代码与EditPad Pro的行为不同。 EditPad是一个用于试验正则表达式的有用测试环境,很高兴知道它有什么问题。

谢谢!

1 个答案:

答案 0 :(得分:1)

我仍然不清楚空字符串的含义是什么,但我能够忽略它们来解决它们。我跟踪搜索字符串中命中的位置,并仅处理字符串中更远的结果。

这是我的代码,没有修改。请注意,我的正则表达式搜索表达式稍有不同,但这对答案并不重要。

void RICommandState::InitRawCommandEnum(const std::string& full_command)
{
    // Split string by colons, but ignore text within quotes.
    static const std::tr1::regex split_by_colon("(?:[^:\"']|\"[^\"]*\"|'[^']*')*");

    raw_command_list.clear();
    raw_command_index = 0;

    std::tr1::sregex_iterator::difference_type minPosition = 0;
    const std::tr1::sregex_iterator end;
    for (std::tr1::sregex_iterator it(full_command.begin(),
                                      full_command.end(),
                                      split_by_colon);
         it != end;
         it++)
    {
        if (it->position() >= minPosition)
        {
            raw_command_list.push_back(it->str());
            minPosition = it->position() + it->length() + 1;
        }
    }
}