【发布时间】: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 是一个有用的测试环境,用于试验正则表达式,很高兴知道其中的陷阱是什么。
谢谢!
【问题讨论】:
-
如果去掉周围的
()?会发生什么?我怀疑这可能允许匹配是可选的,并且由于字符:不匹配,因此从技术上讲,可选匹配匹配,因此打印了空捕获。虽然只是一个理论...... -
没有最外面的括号它只匹配一个字符,但这给了我一个想法。
(([^:\"']|\"[^\"]\"|'[^']')*)似乎在编辑板中工作。我明天回办公室试试看。