使用perl从文件中删除出现的#ifdef/#endif

ohfgkhjo  于 2022-11-15  发布在  Perl
关注(0)|答案(3)|浏览(164)

我有一个代码文件,在构建一个库之后,我想在头文件中删除一些#ifdef。我的第一个想法是将其作为XCode可以运行的Perl脚本来完成。虽然我当然可以打开头文件并将其所有内容读入Perl字符串,但我很好奇完成以下操作的最佳方式
1.查找任何#ifdef示例示例
1.删除它以及以下#endif之间的任何内容
所以这个例子是:

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

并且输出将是:

int i;
NSString *someString;
bool done;

我正在考虑的选项:

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

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

2nbm6dog

2nbm6dog1#

我不知道为什么要去掉ifdef,也许可以用C预处理器来做,但这里是用Perl来做的,因为这意味着我可以使用flip-flop运算符.
第一件事是创建一个足够的正则表达式来匹配ifdefs。IIRC它们可以缩进,并且在#和单词之间可以有缩进。

#ifdef
#    ifdef
    #ifdef

不确定最后一条是否有效,但我还是要用它。

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

如果只是删除#ifdef#endif之间的文本,Perl有很少使用的触发器标量..操作符。

#!/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;
yv5phkfx

yv5phkfx2#

我喜欢正则表达式,但对于这个问题,我不会使用正则表达式,我只是逐行读取,跟踪我是否在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)
1.使^和$在行边界匹配,而不仅仅是字符串边界(m)

  1. Make . match换行(s)
    您可能需要在每个#ifdef#endif后面加上\s,以便仅在该字符串后面有空格时进行匹配。
j0pj023g

j0pj023g3#

我只需要使用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

相关问题