奇怪的正则表达式匹配行为。我的正则表达式错了吗?还是编译器错误?
Weird regex match behavior. Is my regex wrong? Or is it a compiler error?
我正在使用 C++ 中的正则表达式做一些工作,尝试了 std::regex 和 boost:regex (1.58.0)。
我得到了这个奇怪的匹配项。这是代码:
#include <iostream>
#include <regex>
using namespace std;
int main(int argv, const char* argc[])
{
regex log_line_regex_(".+\s(.+)$");
char* log_line = "06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState";
smatch matches;
if (regex_match(std::string(log_line), matches, log_line_regex_))
{
std::cout << "match: " << log_line << std::endl;
unsigned i;
for (i = 0; i < matches.size(); i++)
{
std::cout << "$" << i << ": " << std::string(matches[i].first, matches[i].second) << std::endl;
}
}
return 0;
}
结果是:
match: 06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState
[=11=]: 06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeSt`
: ModeSt`
看到了吗?输出被破坏:(
正如我所说,我在 Cygwin
上尝试使用 boost 1.58.0
和 g++ (GCC) 4.9.2
我觉得 boost::regex 在这个简单的正则表达式中失败很奇怪。那么我的用法有误吗?
这是实施质量。
有两个问题在起作用:
大多数 std 库实现没有很好地、完全地或根本没有实现 std::regex
。这是混淆的常见来源。 IIRC GCC 仅支持 5.x 以上。
另一个问题是您输入的 (std::string(log_line)
) 是临时的 (!)。 smatch
将包含 return 迭代器到一个临时文件中,临时文件的生命周期在 regex_match
调用结束时结束。
修复它至少可以让 GCC 工作 5.x:
#include <iostream>
#include <regex>
int main()
{
std::regex log_line_regex_(".+?\s(.+)");
char const *log_line = "06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState";
std::smatch matches;
std::string input(log_line);
if (regex_match(input, matches, log_line_regex_))
{
std::cout << "match: " << log_line << std::endl;
for (unsigned i = 0; i < matches.size(); i++) {
std::cout << "$" << i << ": " << std::string(matches[i].first, matches[i].second) << std::endl;
}
}
}
打印:
match: 06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState
[=11=]: 06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState
: 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState
¹ 实际上包含 完整表达式
我正在使用 C++ 中的正则表达式做一些工作,尝试了 std::regex 和 boost:regex (1.58.0)。
我得到了这个奇怪的匹配项。这是代码:
#include <iostream>
#include <regex>
using namespace std;
int main(int argv, const char* argc[])
{
regex log_line_regex_(".+\s(.+)$");
char* log_line = "06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState";
smatch matches;
if (regex_match(std::string(log_line), matches, log_line_regex_))
{
std::cout << "match: " << log_line << std::endl;
unsigned i;
for (i = 0; i < matches.size(); i++)
{
std::cout << "$" << i << ": " << std::string(matches[i].first, matches[i].second) << std::endl;
}
}
return 0;
}
结果是:
match: 06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState
[=11=]: 06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeSt`
: ModeSt`
看到了吗?输出被破坏:( 正如我所说,我在 Cygwin
上尝试使用boost 1.58.0
和 g++ (GCC) 4.9.2
我觉得 boost::regex 在这个简单的正则表达式中失败很奇怪。那么我的用法有误吗?
这是实施质量。
有两个问题在起作用:
大多数 std 库实现没有很好地、完全地或根本没有实现
std::regex
。这是混淆的常见来源。 IIRC GCC 仅支持 5.x 以上。另一个问题是您输入的 (
std::string(log_line)
) 是临时的 (!)。smatch
将包含 return 迭代器到一个临时文件中,临时文件的生命周期在regex_match
调用结束时结束。
修复它至少可以让 GCC 工作 5.x:
#include <iostream>
#include <regex>
int main()
{
std::regex log_line_regex_(".+?\s(.+)");
char const *log_line = "06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState";
std::smatch matches;
std::string input(log_line);
if (regex_match(input, matches, log_line_regex_))
{
std::cout << "match: " << log_line << std::endl;
for (unsigned i = 0; i < matches.size(); i++) {
std::cout << "$" << i << ": " << std::string(matches[i].first, matches[i].second) << std::endl;
}
}
}
打印:
match: 06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState
[=11=]: 06-29 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState
: 18:20:08.938 1031 1099 D WifiStateMachine: processMsgConnect oo ModeState
¹ 实际上包含 完整表达式