0

我正在研究一个准 SCPI 命令解析器,我想根据冒号拆分一个字符串,忽略带引号的字符串。如果冒号之间没有文本,我想得到一个空字符串。

如果我在 EditPad Pro 7.2.2 中使用这个正则表达式,它完全符合我的要求。(([^:\"']|\"[^\"] \"|'[^'] ')+)?

例如,使用以下数据字符串: :foo:::bar:baz

我得到 6 次点击:[empty],foo,[empty],[empty],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 是一个有用的测试环境,用于试验正则表达式,很高兴知道其中的陷阱是什么。

谢谢!

4

1 回答 1

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;
        }
    }
}
于 2013-09-04T22:18:19.580 回答