【问题标题】:Regex to replace Boolean with bool正则表达式用 bool 替换 Boolean
【发布时间】:2008-09-19 02:13:00
【问题描述】:

我正在研究最近从 X/Motif 转移到 Qt 的 C++ 代码库。我正在尝试编写一个 Perl 脚本,它将所有出现的布尔值(来自 X)替换为 bool。该脚本只是做一个简单的替换。

s/\bBoolean\b/bool/g

有几个条件。

1) 我们的代码中有 CORBA,并且 \b 匹配 CORBA::Boolean 应该更改。
2) 如果它被发现为字符串(即“Boolean”),则不应匹配

更新:

对于#1,我使用了lookbehind

s/(?<!:)\bBoolean\b/bool/g;

对于 #2,我使用了前瞻。

s/(?<!:)\bBoolean\b(?!")/bool/g</pre>

这很可能适用于我的情况,但以下改进如何?

3) 如果在字符串中间,则不匹配(感谢nohat)。
4)如果在评论中,不要匹配。 (// 或 /**/)

【问题讨论】:

标签: regex perl


【解决方案1】:

s/[^:]\bBoolean\b(?!")/bool/g

这不匹配布尔值位于行首的字符串,因为 [^:] 是“匹配不是:的字符”。

【讨论】:

    【解决方案2】:

    注意与引用匹配的前瞻断言。只有当 Boolean 是字符串的最后一部分,而不是在字符串的中间时,才会匹配。如果您想确保自己不在字符串中(假设没有多行字符串并且没有转义的嵌入式引号),则需要在匹配项之前匹配偶数个引号。

    【讨论】:

      【解决方案3】:
      s/[^:]\bBoolean\b[^"]/bool/g
      

      编辑:老鼠,又被打了。 +1 打败我,好先生。

      【讨论】:

        【解决方案4】:
        #define Boolean bool
        

        让预处理器处理这个问题。每次看到布尔值时,您都可以手动修复它,或者希望正则表达式不会出错。根据您使用的宏数量,您可以从 cpp 中转储。

        【讨论】:

          【解决方案5】:

          修复条件 1 尝试:

          s/[^:]\bBoolean\b(?!")/bool/g
          

          [^:] 表示匹配“:”以外的任何字符。

          【讨论】:

            【解决方案6】:

            3) 如果在字符串中间,则不匹配(感谢 nohat)。

            您也许可以编写一个正则表达式来检查“.*Boolean.*”。但是如果你在字符串中有引号(“)呢?所以,你有更多的工作来不排除 (\") 模式。

            4) 如果在评论中,则不匹配。 (// 或 /* */)

            对于“//”,您可以使用正则表达式来排除 //.* 但是,最好先放置一个正则表达式来比较 // cmets ((.*)(//.*) 的整行)) 然后仅在 $1 (第一个匹配模式)上应用替换。

            对于 /* */,它更复杂,因为这是多行模式。一种方法可以是首先运行整个代码以匹配多行 cmets,然后只取出不匹配的部分......类似于...... (.*)(/*.**/)(.*)。但是,实际的正则表达式会更加复杂,因为您不会有一个而是更多的多行 cmets。

            现在,如果你在 // 块中有 /* 或 */ 怎么办? (我不知道你为什么会拥有它。但墨菲定律说你可以拥有它)。显然有一些出路,但我的想法是强调正则表达式会变得多么糟糕。

            我的建议是为 C++ 使用一些词法工具,并将标记 Boolean 替换为 bool。你的想法?

            【讨论】:

              【解决方案7】:

              为了避免在 perl 中编写完整的 C 解析器,您正在努力取得平衡。根据需要改变的程度,我倾向于做一些非常严格的 s/// 之类的事情,然后将任何仍然匹配 /Boolean/ 的内容写入异常文件以供人类决策。这样您就不会尝试解析可能存在的 C 中间字符串、多行注释、条件编译文本等。

              【讨论】:

                【解决方案8】:
                1. 如果在字符串中间,则不匹配(感谢 nohat)。
                2. 如果在评论中,则不匹配。 (// 或 /**/)

                简单正则表达式不行。为此,您实际上需要从左到右查看 每个单个 字符并确定它是什么类型的东西,至少足以区分 cmets 与多行 cmets 与其他字符串东西,然后然后你需要看看“其他东西”部分是否包含你想要改变的东西。

                现在,我不知道 C++ 中 cmets 和字符串的确切语法规则,因此以下内容将不精确且完全未经调试,但它会让您了解复杂性你反对。

                my $line_comment      = qr! (?> // .* \n? ) !x;
                my $multiline_comment = qr! (?> /\* [^*]* (?: \* (?: [^/*] [^*]* )? )* )* \*/ ) !x;
                my $string            = qr! (?> " [^"\\]* (?: \\ . [^"\\]* )* " ) !x;
                my $boolean_type      = qr! (?<!:) \b Boolean \b !x;
                
                $code =~ s{ \G (
                      $line_comment
                    | $multiline_comment
                    | $string
                    | ( $boolean_type )
                    | .
                ) }{
                    defined $2 ? 'bool' : $1
                }gex;
                

                请不要让我解释这一切错综复杂的事情,这需要我一天又一天的时间。如果您想确切了解这里发生了什么,只需购买并阅读 Jeff Friedl 的 Mastering Regular Expressions

                【讨论】:

                  【解决方案9】:

                  “字符串中间的'布尔'”部分听起来有点不太可能,我会先检查代码中是否出现类似

                  m/"[^"]*Boolean[^"]*"/
                  

                  如果没有或很少,请忽略这种情况。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2019-01-24
                    • 2020-11-05
                    • 2014-03-29
                    • 2015-01-24
                    • 1970-01-01
                    • 2015-11-30
                    • 1970-01-01
                    相关资源
                    最近更新 更多