正则表达式无法从字符串中提取双参数子字符串

Posted

技术标签:

【中文标题】正则表达式无法从字符串中提取双参数子字符串【英文标题】:Regex fails to extract a double parameter substring from a string 【发布时间】:2014-11-04 15:33:29 【问题描述】:

我正在尝试使用 Regex 库工具从文本文件中提取双精度和整数参数。这是捕获我收到的“std::regex_error”消息的最小代码:

#include <iostream>
#include <string>
#include <regex>

int main ()

  std::string My_String = "delta = -002.050";
  std::smatch Match;
  std::regex Base("/^[0-9]+(\\.[0-9]+)?$"); 

  std::regex_match(My_String,Match,Base);

  std::ssub_match Sub_Match = Match[1];
  std::string Sub_String = Sub_Match.str();
  std::cout << Sub_String << std::endl;

  return 0;

我对 Regex 库不太熟悉,也找不到任何立即有用的东西。知道是什么原因导致此错误消息吗?为了编译我的代码,我使用启用了 -std=c++11 的 g++。但是,我确信问题不是由我的 g++ 编译器引起的,正如the answers given to this earlier question 中所建议的那样(我试过several g++ compilers here)。

我希望从字符串“delta = -002.050”中得到“-002.050”,但我得到了:

在抛出 'std::regex_error' 的实例后调用终止 什么():正则表达式错误 中止

【问题讨论】:

到底是什么问题,你期望的输出是什么,你得到了什么? 谢谢。我刚刚编辑了我的帖子。 【参考方案1】:

假设您有 gcc4.9(旧版本不附带支持 &lt;regex&gt; 的 libstdc++ 版本),那么您可以通过将 regex 更改为

std::regex Base("[0-9]+(\\.[0-9]+)?");

这将捕获输入中浮点数的小数部分以及小数点。

您原来的regex 存在一些问题。我认为领先的/ 是一个错误。然后你试图通过将正则表达式括在^...$ 中来匹配整个字符串,这显然不是你想要的。

最后,由于您只想匹配输入字符串的一部分,而不是整个内容,因此您需要使用regex_search 而不是regex_match

std::regex Base(R"([0-9]+(\.[0-9]+)?)"); // use raw string literals to avoid
                                         // having to escape backslashes

if(std::regex_search(My_String,Match,Base)) 
  std::ssub_match Sub_Match = Match[1];
  std::string Sub_String = Sub_Match.str();
  std::cout << Sub_String << std::endl;

Live demo


我希望从字符串“delta = -002.050”中得到“-002.050”

为此,请将上例中的正则表达式修改为

std::regex Base(R"(([+-]0,1[0-9]+\.[0-9]+))");

上面将匹配单个可选的前导 +- 符号。

【讨论】:

【参考方案2】:

前导正斜杠看起来不正确。此外,由于前导 ^ 和尾随 $,您似乎正在尝试匹配整行,但我不确定这是否是您想要的。此外,您的表达式与负号不匹配。

试试这个:

std::regex Base("-?[0-9]+(\\.[0-9]+)?$");

【讨论】:

【参考方案3】:

我认为您遇到了错误,因为 what 在 smatch 对象中 无效。

为避免这种情况,您必须检查是否匹配。

除了一般的正则表达式是

 #  "(?<![-.\\d])(?=[-.\\d]*\\d)(-?\\d*)(\\.\\d*)?(?![-.\\d])"

 (?<! [-.\d] )       # Lookbehind, not these chars in behind
                     # This won't match like  -'-3.44'
                     # Remove if not needed

 (?= [-.\d]* \d )    # Lookahead, subject has to contain a digit

                     # Here, all the parts of a valid number are
                     # in front, now just define an arbitrary form 
                     # to pick them out.
                     # Note - the form is all optional, let the engine
                     # choose what to match.
                     # -----------------  

 ( -? \d* )          # (1), Required group before decimal, can be empty
 ( \. \d* )?         # (2), Optional group, can be null
                     #      change to (\.\d*) if decimal required

 (?! [-.\d] )        # Lookahead, not these chars in front
                     # This won't match like  '3.44'.66
                     # Remove if not needed

示例输出:

 **  Grp 0 -  ( pos 9 , len 8 ) 
-002.050  
 **  Grp 1 -  ( pos 9 , len 4 ) 
-002  
 **  Grp 2 -  ( pos 13 , len 4 ) 
.050  

-----------------

 **  Grp 0 -  ( pos 28 , len 3 ) 
.65  
 **  Grp 1 -  ( pos 28 , len 0 )  EMPTY 
 **  Grp 2 -  ( pos 28 , len 3 ) 
.65  

-----------------

 **  Grp 0 -  ( pos 33 , len 4 ) 
1.00  
 **  Grp 1 -  ( pos 33 , len 1 ) 
1  
 **  Grp 2 -  ( pos 34 , len 3 ) 
.00  

-----------------

 **  Grp 0 -  ( pos 39 , len 4 ) 
9999  
 **  Grp 1 -  ( pos 39 , len 4 ) 
9999  
 **  Grp 2 -  NULL 

-----------------

 **  Grp 0 -  ( pos 104 , len 4 ) 
-99.  
 **  Grp 1 -  ( pos 104 , len 3 ) 
-99  
 **  Grp 2 -  ( pos 107 , len 1 ) 
.  

【讨论】:

以上是关于正则表达式无法从字符串中提取双参数子字符串的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式多引号选择

使用正则表达式从 mysql 列中提取子字符串

使用正则表达式从 Ruby 中的字符串中提取子字符串

如何使用正则表达式或子字符串从字符串中提取文本?

使用正则表达式从句子中的方括号中提取剩余的子字符串

Java使用正则表达式提取字段分隔的子字符串