首页 > 解决方案 > 正则表达式查找具有两个匹配相同正则表达式但仍然不同的捕获组的行

问题描述

我正在尝试分析我的源代码(用 C 编写)以查找不对应的计时器变量比较/分配。我有很多不同时基(2-250 毫秒)的计时器。每个计时器变量的名称(例如timer10ms)以及每个计时器照片和定义(例如fooTimer10msDOO_TIMEOUT_100MS)中都包含以毫秒为单位的粒度。

以下是一些示例行:

fooTimer10ms = timer10ms;
baaTimer20ms = timer10ms;
if (DIFF_100MS(dooTimer10ms) >= DOO_TIMEOUT_100MS)
if (DIFF_100MS(dooTimer10ms) < DOO_TIMEOUT_100MS)

我想匹配时基不对应的那些行(在这种情况下是第二、第三和第四行)。到目前为止,我有这个正则表达式:

(\d{1,3}(?i)ms(?-i)).*[^\d](\d{1,3}(?i)ms(?-i))

能够找到有其中两个粒度的每一行。因此,它不仅仅匹配第 2、3 和 4 行,而是匹配所有这些。我不得不缩小范围的唯一想法是添加一个带有反向引用的负面回顾,如下所示:

(\d{1,3}(?i)ms(?-i)).*[^\d](\d{1,3}(?i)ms(?-i))(?<!\1)

但这是不允许的,因为负后视必须具有固定长度。

我发现了这两个问题(),但拳头没有限制让两个捕获组属于同一类型,第二个是寻找相同的捕获组实例。

如果我想要的东西可以通过使用正则表达式以外的东西更容易地实现,我会很高兴知道。由于我相信正则表达式能够做到这一点,我的想法只是卡住了,而我只是没有足够的创造力来正确使用它。

标签: regex

解决方案


一种选择是匹配后跟数字的计时器部分,并使用带有反向引用的负前瞻来断言它不会出现在右侧。

对于示例数据,使用 2-250 范围的位特定模式可能是:

.*?(timer(?:2[0-4]\d|250|1?\d\d|[2-9])ms)\b\S*[^\S\r\n]*[<>]?=[^\S\r\n]*\b(?!\S*\1)\S+

模式匹配

  • .*?尽可能匹配除换行符以外的任何字符(非贪婪)
  • (捕获组 1
    • timer从字面上匹配
    • (?:2[0-4]\d|250|1?\d\d|[2-9])匹配 2-250 范围内的数字
    • ms从字面上匹配
  • )\b关闭组和单词边界
  • \S*[^\S\r\n]*匹配可选的非空白字符和不带换行符的可选空格
  • [<>]?=匹配可选的<>=
  • [^\S\r\n]*\b匹配没有换行符和单词边界的可选空白字符
  • (?!\S*\1)负前瞻,断言值中第 1 组中捕获的内容不发生
  • \S+匹配 1+ 个非空白字符

正则表达式演示

或者更广泛的模式匹配 1-3 位数字和可选的空白字符,也可能匹配换行符:

.*?(timer\d{1,3}ms\b)\S*\s*[<>]?=\s*\b(?!.*\1)\S+

正则表达式演示

请注意,{1-3}应该{1,3}也可以匹配 999


推荐阅读