8

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

s/\bBoolean\b/bool/g

有几个条件。

1) 我们的代码中有 CORBA,并且 \b 匹配不应更改的 CORBA:: Boolean
2) 如果它被找到为一个字符串,它不应该匹配(即“布尔”)

更新:

对于#1,我使用了lookbehind

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

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

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

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

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

4

9 回答 9

3

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

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

于 2008-08-29T20:20:09.697 回答
2

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

于 2008-08-29T21:36:34.457 回答
1
#define Boolean bool

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

于 2008-09-18T18:13:00.860 回答
1
s/[^:]\bBoolean\b[^"]/bool/g

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

于 2008-08-29T20:12:20.620 回答
0
  1. …</li>
  2. …</li>
  3. 如果在字符串中间,则不匹配(感谢 nohat)。
  4. 如果在评论中不匹配。(// 或者 /**/)

没有一个简单的正则表达式。为此,您实际上需要从左到右查看每个字符并确定它是什么类型的东西,至少足以将注释与多行注释与其他内容的字符串区分开来,然后您需要查看“其他内容”部分是否包含您要更改的内容。

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

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 。

于 2008-09-17T19:49:28.983 回答
0

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

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

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

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

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

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

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

于 2008-09-04T13:14:28.873 回答
0

要修复条件 1,请尝试:

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

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

于 2008-08-29T20:11:28.967 回答
0

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

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

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

于 2008-09-18T00:35:43.757 回答
0

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

于 2008-09-17T19:20:53.263 回答