Regex C++;11正则表达式搜索-排除空子匹配

Regex C++;11正则表达式搜索-排除空子匹配,regex,c++11,regex-group,Regex,C++11,Regex Group,我想从以下文本中提取数字和计量单位 我有两种可能的情况: 这是一些文字14.56千克和一些其他文字 或 这是一些文本kg 14.56和一些其他文本 我使用|来匹配这两种情况。 我的问题是,它会产生空的子匹配,从而给我一个不正确的匹配数 这是我的代码: std::smatch m; std::string myString = "This is some text kg 14.56 and some other text"; const std::regex myRegex( R

我想从以下文本中提取
数字
计量单位

我有两种可能的情况:

这是一些文字
14.56千克
和一些其他文字

这是一些文本
kg 14.56
和一些其他文本

我使用
|
来匹配这两种情况。 我的问题是,它会产生空的子匹配,从而给我一个不正确的匹配数

这是我的代码:

std::smatch m;
std::string myString = "This is some text kg 14.56 and some other text";

const std::regex myRegex(
        R"(([\d]{0,4}[\.,]*[\d]{1,6})\s+(kilograms?|kg|kilos?)|s+(kilograms?|kg|kilos?)(\s+[\d]{0,4}[\.,]*[\d]{1,6}))",
        std::regex_constants::icase
);

if( std::regex_search(myString, m, myRegex) ){
    std::cout << "Size: " << m.size() << endl;
    for(int i=0; i<m.size(); i++)
        std::cout << m[i].str() << std::endl;
}
else
    std::cout << "Not found!\n";
我想要一种简单的方法来提取这两个值,所以我想我想要以下输出:

想要的输出:

Size: 3
kg 14.56
kg
14.56
这样,我总是可以直接提取第二和第三,但在这种情况下,我还需要检查哪一个是数字。我知道如何用2个单独的搜索来做,但是我想用正确的方式来做,用一个搜索,而不用C++来检查子匹配是否是空字符串。p> 您可以尝试以下方法:

((?:(?<!\d)(\d{1,4}(?:[\.,]\d{1,6})?)\s+((?:kilogram|kilos|kg)))|(?:((?:kilogram|kilos|kg))\s+(\d{1,4}(?:[\.,]\d{1,6})?)))
((?:(?)?
如图所示:

用法- 正如我在“替换”部分中所示,要引用数量的数字部分,您必须写$2$5,对于单位,写:$3$4

解释- 我们可能需要两个捕获组:这里的第一个组是匹配数字,后面是单元,
另一个
(?:(?:kg | kilos | kg))\s+(\d{1,4}(?:[\,]\d{1,6})
要匹配后面跟数字的单位,您可以尝试以下方法:

((?:(?<!\d)(\d{1,4}(?:[\.,]\d{1,6})?)\s+((?:kilogram|kilos|kg)))|(?:((?:kilogram|kilos|kg))\s+(\d{1,4}(?:[\.,]\d{1,6})?)))
((?:(?)?
如图所示:

用法- 正如我在“替换”部分中所示,要引用数量的数字部分,您必须写$2$5,对于单位,写:$3$4

解释- 我们可能需要两个捕获组:这里的第一个组是匹配数字,后面是单元,

另一个
(?:(?:kg | kilos | kg))\s+(\d{1,4}(?:[\,]\d{1,6})
要匹配后面跟数字的单位,使用这个正则表达式,只需要组1和组2的内容

((?:kilograms?|kilos?|kg)|(?:\d{0,4}(?:\.\d{1,6})))\s*((?:kilograms?|kilos?|kg)|(?:\d{0,4}(?:\.\d{1,6})))

说明:

  • ((?:千克?|千克?|千克)(?:\d{0,4}(?:\.\d{1,6}))
    • (?:千克?|千克?|千克)
      -匹配
      千克
      千克
      千克
      千克
    • |
      -或
    • (?:\d{0,4}(?:\.\d{1,6}))
      -匹配0到4位数字,后跟小数部分的1到6位
  • \s*
    -匹配0+个空格

使用此正则表达式,您只需要组1和组2的内容

((?:kilograms?|kilos?|kg)|(?:\d{0,4}(?:\.\d{1,6})))\s*((?:kilograms?|kilos?|kg)|(?:\d{0,4}(?:\.\d{1,6})))

说明:

  • ((?:千克?|千克?|千克)(?:\d{0,4}(?:\.\d{1,6}))
    • (?:千克?|千克?|千克)
      -匹配
      千克
      千克
      千克
      千克
    • |
      -或
    • (?:\d{0,4}(?:\.\d{1,6}))
      -匹配0到4位数字,后跟小数部分的1到6位
  • \s*
    -匹配0+个空格


  • 请注意,我使用默认的正则表达式引擎,这是ECMAScript。我看到它产生以下错误:“前面的令牌是不可量化的”Nope,我使用C++。11@Boy好的,让我检查一下,againC++返回了这个错误:“无效的特殊开括号。”你好,谢谢你的帮助。请注意我使用默认的正则表达式引擎,这是ECMAScript。我看到它会产生以下错误:“前面的令牌是不可量化的”Nope,我用C++。11@Boy好的,让我检查一下,againC++返回了这个错误:“无效的特殊开括号。”我已经编辑了我的答案,它工作了-但是你可能想等待解释,我已经编辑了我的答案,它工作了-但是你可能也想等待解释,嗨,有什么方法可以按相同的顺序返回组吗?我读到ECMAScript不允许命名组:按“相同的顺序”,您的意思是,对于这两个示例,组1应该包含数值,组2应该包含单位吗?这个整数问题可以通过如下所示的轻微修改来解决。对于第一个问题,我认为您可以通过编程方式检查每个组的内容。如果内容是非数值的,则意味着您可以我已经捕获了该单元,否则您已经捕获了该值。不用担心,兄弟。如果我提出更好的解决方案来包含您的阴性测试用例,我将更新该解决方案。我将在办公时间后再试一次。很高兴该解决方案对您有所帮助:)嗨,有没有办法按相同的顺序返回组?我听说ECMAScript不允许按“相同的顺序”返回命名组,您的意思是,对于这两个示例,组1应该包含数值,组2应该包含单位吗?这个整数问题可以通过如下所示的轻微修改来解决。对于第一个问题,我认为您可以通过编程方式检查每个组的内容。如果内容是非数值的,则意味着您可以我已经捕获了该单元,否则您已经捕获了该值。不用担心,兄弟。如果我提出更好的解决方案来包含您的阴性测试用例,我将更新该解决方案。我将在办公时间后再试一次。很高兴该解决方案对您有所帮助:)