C++ regex_match找不到转义字符



这是一个关于我在regex_match做错了什么的问题。似乎转义字符,例如+,.和 \d(加号、十进制符号和任何数字)不匹配。此外,似乎只有贪婪的匹配才有效(所以没有"?")。

我有一个在 Ubuntu 18.04 上编写的程序,并使用 g++ (gcc 7.5.0) 构建。目标是解析传感器实用程序输出的温度。下面是一个截断的示例,说明了我的问题。为什么不进行临时解析?

#include <iostream>
#include <stdexcept>
#include <regex>
char sensorData[][250]={
"radeon-pci-0008n",
"Adapter: PCI adaptern",
"temp1:        +47.0°C  (crit = +120.0°C, hyst = +90.0°C)n",
"n",
"fam15h_power-pci-00c4n",
"Adapter: PCI adaptern",
"power1:        7.79 W  (interval =   0.01 s, crit =  15.05 W)n",
"n",
"k10temp-pci-00c3n",
"Adapter: PCI adaptern",
"temp1:        +47.1°C  (high = +70.0°C)n",
"                       (crit = +105.0°C, hyst = +104.0°C);n"};
float extractTemperature(std::string sensorData){
//std::regex e("\+(.)*?C");  //nope
//std::regex e("\d\d(.)*?C"); //nope
//std::regex e("temp1(.)*C"); //yes all day long
std::regex e("\+(\d\d\.\d)(.)*?C"); //nope
std::smatch match;
float temperature = 0.0;
std::cout << "evaluating: " << sensorData;
if (sensorData.length()>1){
//something about n confuses regex. Strip last char
sensorData = sensorData.substr(0,sensorData.length()-1);
if(std::regex_match(sensorData,match,e)){
for (unsigned i=0; i<match.size(); ++i){
std::cout<<"["<<match[i]<<"]";
}
} //else std::cout << "no match";
}//else: only one char... meh, skipping
//assumes our regex parses out a /d/d/./d
try{
float temperature = std::stof(sensorData);
}catch(...){};  
return temperature;
}
int main(int argc, char *argv[])
{
for (int line = 0; line < 12; line++){
std::cout << "temp extracted is: " << extractTemperature(std::string(sensorData[line])) << std::endl;
}
return 0;
}

当我在 regex101.com 尝试我的表达式时,我可以看到表达式:

+(dd.d)(.)*?C

匹配字符串:

"temp1:        +45.0°C  (crit = +120.0°C, hyst = +90.0°C"

并产生两组,一组是温度"45.0"!太棒了 - 但我无法在C++中复制它

如果我简单地编译:

g++ 1.cc -o extractTemp

输出为:

temp extracted is: evaluating: radeon-pci-0008
0
temp extracted is: evaluating: Adapter: PCI adapter
0
temp extracted is: evaluating: temp1:        +47.0°C  (crit = +120.0°C, hyst = +90.0°C)
0
temp extracted is: evaluating: 
0
temp extracted is: evaluating: fam15h_power-pci-00c4
0
temp extracted is: evaluating: Adapter: PCI adapter
0
temp extracted is: evaluating: power1:        7.79 W  (interval =   0.01 s, crit =  15.05 W)
0
temp extracted is: evaluating: 
0
temp extracted is: evaluating: k10temp-pci-00c3
0
temp extracted is: evaluating: Adapter: PCI adapter
0
temp extracted is: evaluating: temp1:        +47.1°C  (high = +70.0°C)
0
temp extracted is: evaluating:                        (crit = +105.0°C, hyst = +104.0°C);
0

那么,为什么我的体温没有在"temp1:"行上解析呢?

注意:我认为特殊字符不需要单转义或三转义(例如\d或\\d),这只会导致编译器抱怨无法识别的字符

你应该使用原始字符串:

原始字符串文本。用于避免转义任何字符。什么 分隔符之间成为字符串的一部分。- cppreference.com

在您的情况下,它将如下所示:

// ... 
std::regex expression(R"(d+.d+°C)");
// ...

总的来说,你的代码中有一些过度复杂(显式n管理,循环match)和错误(重新声明temperature)。因此,您应该以以下形式为目标:

double extractTemperature(std::string sensorData){
std::regex expression(R"(d+.d+°C)");
std::smatch match;
double temperature = 0;
if (sensorData.size()>1) {
std::regex_search(sensorData, match, expression);
if (match.size() > 0) {
std::cout << '[' << match[0] << ']' << 'n';
std::string number = match[0];
try { temperature = std::stof(number); }
catch (...) {
std::cout << "Can't convert: " << number << 'n';
}
return temperature;
}
}
return 0; // Default return, if no sensorData
}
int main() {
for (std::size_t line = 0; line < 12; ++line){
double value = extractTemperature(std::string(sensorData[line]));
if (value)
std::cout << "Extracted: " << value << 'n';
}
}

示例输出:

[47.0°C]
Extracted: 47
[47.1°C]
Extracted: 47.1
[105.0°C]
Extracted: 105

最新更新