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 EXAMPLE のインデックスを見つけ、次に見つかった #endif の部分文字列を介してそれを削除します
  • これらの出現をどうにかして取り除くことができる正規表現を書いてください。

以前に Perl を書いたことがないことを考えると (Objective-C が私の主要な言語です)、XCode または Perl の開発者が最善のアプローチについて何か提案があるかどうか知りたいと思いました。

4

3 に答える 3

4

なぜ ifdef を削除したいのかわかりませんが、おそらく C プリプロセッサを使用してこれを行うことができますが、フリップフロップ演算子をいじることになるため、Perl で行う方法を次に示します。 .

最初に、ifdef に一致する十分な正規表現を作成します。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;
于 2013-01-09T21:13:19.123 に答える
1

私は正規表現が大好きですが、この問題では正規表現を使用しません。行ごとに読み取り、ifdef 内にいるかどうかを追跡します。

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

本当に正規表現を使用したい場合で、ファイル全体を variable$sourceに読み込んだ場合、ネストについて心配する必要がなければ、これでうまくいくと思います:

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

文字は、式の^これらの部分を行の先頭に固定します。は$、一致の最後の部分が行末でのみ発生するようにします。

は、最小限の一致を行うことを除いて、0 個以上の文字に一致する と.*?ほとんど同じように動作します。.*そのため、最後の までずっと一致するのではなく#endif、最初のものと一致します。

/gms最後にそれを作ります:

  1. 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 に答える