【问题标题】:Tokenize with colon using std::tr1::regex使用 std::tr1::regex 用冒号标记
【发布时间】:2013-01-12 03:05:07
【问题描述】:

我正在开发一个准 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 是一个有用的测试环境,用于试验正则表达式,很高兴知道其中的陷阱是什么。

谢谢!

【问题讨论】:

  • 如果去掉周围的 ( )? 会发生什么?我怀疑这可能允许匹配是可选的,并且由于字符 : 不匹配,因此从技术上讲,可选匹配匹配,因此打印了空捕获。虽然只是一个理论......
  • 没有最外面的括号它只匹配一个字符,但这给了我一个想法。 (([^:\"']|\"[^\"]\"|'[^']')*) 似乎在编辑板中工作。我明天回办公室试试看。

标签: regex tr1


【解决方案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;
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-12
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多