1

我有一个代码文件,其中包含一些我想在构建库后在头文件中删除的#ifdefs。我的第一个想法是将其作为 XCode 可以运行的 perl 脚本来执行。虽然我当然可以打开头文件并将其所有内容读入 perl 中的字符串,但我很好奇执行以下操作的最佳方法

  1. 查找任何出现的 #ifdef 示例

  2. 删除它以及以下 #endif 之间的任何内容

所以例子是:

int i;
NSString *someString;
#ifdef EXAMPLE
NSString *exampleString;
#endif
bool done;

输出将是:

int i;
NSString *someString;
bool done;

我正在考虑的选项:

  • 查找每个 #ifdef 示例的索引并通过子字符串将其删除,下一个找到的 #endif
  • 编写一个可以以某种方式消除这些事件的正则表达式。

考虑到我之前没有写过 Perl(Objective-C 是我的主要语言),我很好奇是否有任何 XCode 或 Perl 开发人员对最好的方法有什么建议

4

3 回答 3

4

我不知道你为什么要去掉 ifdefs,你可能可以使用 C 预处理器来做到这一点,但这是你在 Perl 中的做法,因为这意味着我可以使用触发器运算符.

首先是制作一个足够的正则表达式来匹配 ifdef。IIRC 它们可以缩进,#并且单词和单词之间可以缩进。

#ifdef
#    ifdef
    #ifdef

不确定最后一个是否有效,但无论如何我都会接受它。

my $ifdef_re = qr{^\s*#\s*ifdef\b};
my $endif_re = qr{^\s*#\s*endif\b};

如果只是删除 and 之间的文本#ifdef#endifPerl 有很少使用的触发器标量..运算符

#!/usr/bin/env perl

use strict;
use warnings;

my $ifdef_re = qr{^\s*#\s*ifdef\b};
my $endif_re = qr{^\s*#\s*endif\b};

while(<DATA>) {
    my $in_ifdef = /$ifdef_re/ .. /$endif_re/;

    print if !$in_ifdef;
}

__DATA__
int i;
NSString *someString;
#ifdef EXAMPLE
NSString *exampleString;
#endif
bool done;

但是由于我们需要担心嵌套的 ifdef,它是不够的。深度计数器可以解决这个问题。

#!/usr/bin/env perl

use strict;
use warnings;

my $ifdef_re = qr{^\s*#\s*ifdef\b};
my $endif_re = qr{^\s*#\s*endif\b};

my $ifdef_count = 0;
while(<DATA>) {
    $ifdef_count++ if /$ifdef_re/;

    print if $ifdef_count <= 0;

    $ifdef_count-- if /$endif_re/;
}

__DATA__
int i;
NSString *someString;
#ifdef EXAMPLE
NSString *exampleString;
#    ifdef FOO
this should not appear
#    endif
nor should this
#endif
bool done;
于 2013-01-09T21:13:19.123 回答
1

我喜欢正则表达式,但是对于这个问题,我不会使用正则表达式,我只是逐行阅读,跟踪我是否在 ifdef 中:

my $nesting = 0;
while (<STDIN>)
   {
   $nesting += 1 if /^#ifdef/;
   print $_ unless $nesting;
   $nesting -= 1 if /^#endif/;
   }

如果您真的想使用正则表达式,并将整个文件读入变量$source,我认为这会起作用,如果您不需要担心嵌套:

$source =~ s/^#ifdef.*?^#endif.*?$//gms;

字符将表达式的^这些部分锚定到行首。$使得匹配的最后部分只发生在一行的末尾。

.*?行为几乎像.*,它匹配零个或多个字符,除了它进行最小匹配。所以不是一直匹配到最后一个#endif,而是匹配第一个。

最后/gms使它:

  1. 替换每一个出现,而不仅仅是一个(那是 g)
  2. 使 ^ 和 $ 在行边界匹配,而不仅仅是字符串边界(m)
  3. 制作 。匹配换行符(s)

您可能希望跟随 every#ifdef#endifwith \s,仅在该字符串后面有空格时才匹配。

于 2013-01-09T21:20:40.267 回答
0

我只是用unifdef. XCode 默认安装这个:

-U will remove #ifdef and matching #else/#endif as if <constant> is undefined.
-D will remove #ifdef and matching #else/#endif as if <constant> is defined.

这是一个例子:

$ cat test.h
#ifdef TEST

#ifdef DEBUG
# define AWESOME_DEBUG_LEVEL 1
#else
# define AWESOME_DEBUG_LEVEL 0
#endif

#endif

$ unifdef -U DEBUG test.h
#ifdef TEST

# define AWESOME_DEBUG_LEVEL 0

#endif

$ unifdef -U DEBUG -D TEST test.h

# define AWESOME_DEBUG_LEVEL 0
于 2016-09-04T10:09:37.180 回答