正则表达式检测以分号结尾的 C++ for 和 while 循环

2025-02-11 09:51:00
admin
原创
59
摘要:问题描述:在我的 Python 应用程序中,我需要编写一个正则表达式来匹配以分号 ( ) 结尾的C++for或循环。例如,它应该匹配以下内容:while`;`for (int i = 0; i < 10; i++); ...但不是这个:for (int i = 0; i < 10; i++) 乍一...

问题描述:

在我的 Python 应用程序中,我需要编写一个正则表达式来匹配以分号 ( ) 结尾的C++for或循环。例如,它应该匹配以下内容:while`;`

for (int i = 0; i < 10; i++);

...但不是这个:

for (int i = 0; i < 10; i++)

乍一看这似乎微不足道,直到您意识到开括号和闭括号之间的文本可能包含其他括号,例如:

for (int i = funcA(); i < funcB(); i++);

我正在使用 python.re 模块。现在我的正则表达式如下所示(我保留了我的注释,以便您更容易理解):

# match any line that begins with a "for" or "while" statement:
^s*(for|while)s*
(  # match the initial opening parenthesis
    # Now make a named group 'balanced' which matches a balanced substring.
    (?P<balanced>
        # A balanced substring is either something that is not a parenthesis:
        [^()]
        | # …or a parenthesised string:
        ( # A parenthesised string begins with an opening parenthesis
            (?P=balanced)* # …followed by a sequence of balanced substrings
        ) # …and ends with a closing parenthesis
    )*  # Look for a sequence of balanced substrings
)  # Finally, the outer closing parenthesis.
# must end with a semi-colon to match:
s*;s*

这对于所有上述情况都有效,但是当您尝试使 for 循环的第三部分包含一个函数时,它就会中断,如下所示:

for (int i = 0; i < 10; doSomethingTo(i));

我认为它会中断,因为只要你在开括号和闭括号之间放置一些文本,“平衡”组就会匹配包含的文本,因此该(?P=balanced)部分不再起作用,因为它不会匹配(由于括号内的文本不同)。

在我的 Python 代码中,我使用 VERBOSE 和 MULTILINE 标志,并创建如下正则表达式:

REGEX_STR = r"""# match any line that begins with a "for" or "while" statement:
^s*(for|while)s*
(  # match the initial opening parenthesis
    # Now make a named group 'balanced' which matches
    # a balanced substring.
    (?P<balanced>
        # A balanced substring is either something that is not a parenthesis:
        [^()]
        | # …or a parenthesised string:
        ( # A parenthesised string begins with an opening parenthesis
            (?P=balanced)* # …followed by a sequence of balanced substrings
        ) # …and ends with a closing parenthesis
    )*  # Look for a sequence of balanced substrings
)  # Finally, the outer closing parenthesis.
# must end with a semi-colon to match:
s*;s*"""

REGEX_OBJ = re.compile(REGEX_STR, re.MULTILINE| re.VERBOSE)

有人能建议改进这个正则表达式吗?它对我来说太复杂了,我搞不懂。


解决方案 1:

您可以编写一个非常简单的小例程来完成此操作,而无需使用正则表达式:

  • 设置一个位置计数器pos,使其指向for或之后的左括号之前while

  • 将开括号计数器设置openBr0

  • 现在继续增加pos,读取相应位置的字符,并openBr在看到左括号时增加,并在看到右括号时减少。这将在开始时增加一次,对于“ for (”中的第一个左括号,再增加和减少一些中间的括号,并将其设置回括号关闭0for

  • 那么,何时openBr再来就停止0

终止位置是您的右括号for(...)。现在您可以检查后面是否有分号。

解决方案 2:

这种事情你真的不应该用正则表达式来做。只需一次解析一个字符,并跟踪左括号/右括号。

如果这就是您所寻找的全部,那么您肯定不需要功能齐全的 C++ 语法词法分析器/解析器。如果您想要练习,您可以编写一个小型的递归解析器,但即使这样,对于仅匹配括号来说也有点太多了。

解决方案 3:

这是使用错误工具完成工作的一个很好的例子。正则表达式不能很好地处理任意嵌套的子匹配。你应该做的是使用真正的词法分析器和解析器(C++ 的语法应该很容易找到)并查找意外的空循环体。

解决方案 4:

尝试这个正则表达式

^s*(for|while)s*
(
(?P<balanced>
[^()]*
|
(?P=balanced)
)
s*;s

我删除了环绕( )并将(?P=balanced)移到*任何非括号序列的后面。我曾使用 boost xpressive 进行过这项工作,并重新检查了该网站 ( Xpressive ) 以刷新我的记忆。

解决方案 5:

虽然有点晚了,但是我认为正则表达式不是适合这个工作的工具

问题是您会遇到边缘情况,这会给正则表达式增加额外的复杂性。@est提到了一个示例行:

for (int i = 0; i < 10; doSomethingTo("("));

此字符串文字包含一个(不匹配的!)括号,这破坏了逻辑。显然,您必须忽略字符串文字的内容。为了做到这一点,您必须考虑双引号。但字符串文字本身可以包含双引号。例如,试试这个:

for (int i = 0; i < 10; doSomethingTo("\"(\\\"));

如果您使用正则表达式解决这个问题,它会为您的模式增加更多的复杂性。

我认为你最好解析语言。例如,你可以使用 ANTLR 之类的语言识别工具。ANTLR 是一个解析器生成器工具,它也可以生成Python 中的解析器。你必须提供定义目标语言的语法,在你的情况下是 C++。目前已经有许多适用于许多语言的语法,因此你可以直接获取C++ 语法。

然后您可以轻松地遍历解析器树,搜索空语句whilefor循环体。

解决方案 6:

我甚至不会注意括号的内容。

for只需匹配以分号开头和结尾的任何行:

^    *for.+;$

除非您将for语句分成多行,否则这样可以正常工作?

解决方案 7:

我不知道正则表达式能否很好地处理这种情况。尝试这样做

line = line.Trim();
if(line.StartsWith("for") && line.EndsWith(";")){
    //your code here
}

解决方案 8:

Greg 完全正确。这种解析无法通过正则表达式完成。我认为可以构建一些可怕的怪物,它们在许多情况下都有效,但随后你就会遇到一些可以正常工作的东西。

您确实需要使用更传统的解析技术。例如,编写一个递归解析器来执行您需要的操作非常简单。

解决方案 9:

另一种想法是忽略括号并将视为for包含三个分号分隔值的构造:

fors*([^;]+;[^;]+;[^;]+)s*;

即使分成多行(一旦启用 MULTILINE),此选项仍有效,但假定这for ( ... ; ... ; ... )是唯一有效的构造,因此不适用于for ( x in y )构造或其他偏差。

还假设没有包含分号作为参数的函数,例如:

for ( var i = 0; i < ListLen('a;b;c',';') ; i++ );

这是否是可能的情况取决于你实际这样做的目的。

解决方案 10:

正如 Frank 所建议的,最好不要使用正则表达式。下面是一行(丑陋的)代码:

match_string = orig_string[orig_string.index("("):len(orig_string)-orig_string[::-1].index(")")]

与他在评论中提到的巨魔线相匹配:

orig_string = "for (int i = 0; i < 10; doSomethingTo(\"(\"));"
match_string = orig_string[orig_string.index("("):len(orig_string)-orig_string[::-1].index(")")]

返回(int i = 0; i < 10; doSomethingTo("("))

它的工作原理是向前遍历字符串,直到到达第一个左括号,然后向后遍历,直到到达第一个右括号。然后使用这两个索引来切分字符串。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用