0

正規表現を使用して特定の行を含まないブロックを抽出するために、テキスト ファイルをブロックに分割しています。テキスト ファイルは次のようになります。

[Term]  
id: id1  
name: name1  
xref: type1:aab  
xref: type2:cdc  

[Term]  
id: id2  
name: name2  
xref: type1:aba  
xref: type3:fee 

数日前、誰かが特定の正規表現 (たとえば "xref: type3") を含むブロックを抽出する方法を教えてくれました。

while (<MYFILE>) {
  BEGIN { $/ = q|| }
    my @lines = split /\n/;
    for my $line ( @lines ) {
        if ( $line =~ m/xref:\s*type3/ ) {
            printf NEWFILE qq|%s|, $_;
            last;
        }
    }
}

ここで、「xref: type3」を含まないすべてのブロックを新しいファイルに書き込みたいと考えています。私は単に正規表現を否定することでこれをやろうとしました

if ( $line !~ m/xref:\s*type3/ )

または、代わりに if ステートメントを否定することによって

unless ( $line =~ m/xref:\s*type3/ )

残念ながら動作しません。出力ファイルは元のファイルと同じです。私が間違っていることはありますか?

4

3 に答える 3

3

あなたが持っている:

行ごとに、この行がパターンに一致しない場合は、このブロックを出力します。

しかし、あなたが望む:

すべての行について、ブロック内の他の行がパターンに一致しない場合は、この行を出力します。

そのため、ブロック内のすべての行 (または一致する行が見つかるまですべての行) を調べる前に、ブロックの印刷を開始することはできません。

local $/ = q||;
while (<MYFILE>) {
    my @lines = split /\n/;

    my $skip = 0;
    for my $line ( @lines ) {
        if ( $line =~ m/^xref:\s*type3/ ) {
            $skip = 1; 
            last;
        }
    }

    if (!$skip) {
        for my $line ( @lines ) {
            print NEWFILE $line;
        }
    }
}

しかし、行に分割する必要はありません。ブロック全体を一度に確認して印刷できます。

local $/ = q||;
while (<MYFILE>) {
    print NEWFILE $_ if !/^xref:\s*type3/m;
}

(を任意の行の先頭に一致/mさせることに注意してください。)^

于 2013-07-24T13:41:32.350 に答える
1

問題は、これを行うと一致しないかのように解釈される which を使用unlessしていることです。(二重否定)!~$line

unless通常のパターン マッチング演算子でブロックを使用すると、=~コードは完全に機能しました。つまり、type3 が含まれていないため、最初のブロックが出力として表示されます。

LOOP:
while (<$MYFILE>) {
  BEGIN { $/ = q|| }
    my @lines = split /\n/;
    for my $line ( @lines ) {
        unless ( $line =~ m/xref:\s*type3/ ) {
            printf qq|%s|, $_;
            last LOOP;
        }
  }
}

# prints
# [Term]
# id: id1
# name: name1
# xref: type1:aab
# xref: type2:cdc
于 2013-07-24T13:10:58.573 に答える