-4

Perl の入力レコード セパレータを $/ = "__Data__\n" に設定すると機能しないのはなぜですか?

データ レコードは次のように設定されます。

 __Data__\n
 1aaaaaaaaaa\n
 aaaaaaaaaaa\n
 aaaaaaaaaaaaa\n
 __Data__\n
 1bbbbbbbbbb\n
 bbbbbbbbbbb\n
 bbbbbbbbbbbbb\n
 __Data__\n
 1cccccccccc\n
 ccccccccccc\n
 ccccccccccccc\n
 __Data__\n

以下は、各データ レコードの最初の行にアクセスするための Perl コードです...

$/ = "__Data__\n";

open READFILE, "<", "logA.txt" or die "Unable to open file";

while (<READFILE>)
{
   if (/([^\n]*)\n(.*)/sm)
   {
       print "$1\n";
   }
}
close(<READFILE>);

次の望ましくない出力が得られます。

__Data__

次の望ましい出力ではありません。

1aaaaaaaaaaa
1bbbbbbbbbbb
1ccccccccccc

入力レコード区切りが機能し$/="__Data__";ないのはなぜですか? どのように機能する必要がありますか?

4

2 に答える 2

5

私が質問を正しく理解しているなら、あなたはその部分を取り除きたい__Data__. あなたはこれを求めている...

1aaaaaaaaaa
1bbbbbbbbbb
1cccccccccc

...しかし、あなたはこれを取得しています...

__Data__
1aaaaaaaaaa
1bbbbbbbbbb
1cccccccccc

コマンドを使用しchompて、行末を削除できます。通常、これは単なる改行ですが、chomp設定した内容に応答します$/

use strict;
use warnings;

{
    local $/="__Data__\n";
    open my $fh, "<", "logA.txt" or die "Unable to open file";

    while(my $record = <$fh>) {
        chomp $record;
        print $record;
    }
}

ところで、「行末」の概念を変更したため、__Data__フィールド間のすべてが単一行と見なされます。行を分割する必要がある場合は、 を使用できますmy @lines = split "\n", $record

use strict;
use warnings;

{
    # Isolate the change to the global $/
    local $/="__Data__\n";

    open my $fh, "<", "logA.txt" or die "Unable to open file";

    while(my $record = <$fh>) {
        # Remove the __Data__ separator
        chomp $record;

        # Split the record by line
        my @lines = split /\n/, $record;

        # Empty record, skip it
        next if !@lines;

        # Print the first line of the record
        print $lines[0], "\n";
    }
}

また、コードにいくつかの一般的な改善を加えました。 $/グローバルであり、ファイルを読み取るすべてに影響します。 local変更がブロック内でのみ発生することを保証します。

レキシカル ファイルハンドルを使用しました。これらはスコープ外に出ると (宣言されているブロックが終了すると)、自動的に閉じます。

そして、タイプミスや小さな間違いをキャッチする strict と warnings を有効にしましたclose(<READLINE>)

于 2013-05-17T21:49:37.193 に答える
2

入力.txt

__Data__
1aaaaaaaaaa
aaaaaaaaaaa
aaaaaaaaaaaaa
__Data__
1bbbbbbbbbb
bbbbbbbbbbb
bbbbbbbbbbbbb
__Data__
1cccccccccc
ccccccccccc
ccccccccccccc
__Data__

使用して$/=qq{__Data__\n}

perl -e 'use Data::Dumper;$Data::Dumper::Useqq=1; $/=qq{__Data__\n}; open $fh,"input.txt"; print Dumper [ <$fh> ]'

$VAR1 = [
      "__Data__\n",
      "1aaaaaaaaaa\naaaaaaaaaaa\naaaaaaaaaaaaa\n__Data__\n",
      "1bbbbbbbbbb\nbbbbbbbbbbb\nbbbbbbbbbbbbb\n__Data__\n",
      "1cccccccccc\nccccccccccc\nccccccccccccc\n__Data__"
    ];

使用して$/=qq{Data}

$VAR1 = [
      "__Data",
      "__\n1aaaaaaaaaa\naaaaaaaaaaa\naaaaaaaaaaaaa\n__Data",
      "__\n1bbbbbbbbbb\nbbbbbbbbbbb\nbbbbbbbbbbbbb\n__Data",
      "__\n1cccccccccc\nccccccccccc\nccccccccccccc\n__Data",
      "__"
    ];

自明だと思います。

于 2013-05-18T06:32:46.470 に答える