1

新しい改行が含まれるテキストを含む CSV ファイルがあります。例えば

1,b,hello
world,x
2,a,hello

mars,y

一度にすべて読み取るために、 $/ 特殊変数に正規表現を指定したいと思います。どうすればそれができるかについて何か提案はありますか?

私の考えでは、特殊変数に "(x|y)\n" のようなものを入れると、行が x または y で終わり、新しい行が続く場合をキャプチャする必要があります。

ありがとう

4

3 に答える 3

4

$/ に正規表現を使用することはできません。ただし、ファイルが大きすぎない場合は、全体をスカラーに読み取り、正規表現で分割できます。

@records = split /(x|y)\n/, $data;

于 2012-08-23T18:37:14.940 に答える
3

このようなファイルをレコードに分割する一般的な方法はありません。ファイルの行が現在のレコードに近いのか、それとも新しいレコードの始まりなのかを判断することは不可能だからです。

ただし、仮定できる場合

  • レコードには常に同じ数のフィールドがあります

  • フィールド内のデータにカンマが含まれていない

  • レコードの最後のフィールドが複数行に分割されることはありません

次に、十分な数のフィールドが得られるまで、ファイルから行を単純に蓄積できます

このプログラムは原理を示しています。

use strict;
use warnings;

while (my $record= <>) {
  $record .= <> until $record =~ tr/,// == 3;
  print ">> $record\n";
}

出力

>> 1,b,hello
world,x

>> 2,a,hello

mars,y
于 2012-08-23T19:15:54.220 に答える
2

独自のサブを作成して、一度に 1 つのデータセットを読み取ることができます。

 sub readDataSet {
   my $buffer = '';
   local $/ = "\n";
   $buffer .= <STDIN> until $buffer =~ /(x|y)\n$/;
   return $buffer;
 }

 my $nextRow = readDataSet();

これにより、行全体が返されます。あなたの正規表現は定数部分で終わるので、私はこれを行うことができます。このサブにはいくつかのバリエーションがあります。

  1. 任意のファイルハンドルから読み取ります:

    sub readDataSet {
      my ($filehandle) = @_;
      my $buffer = "";
      $buffer .= <$filehandle> until $buffer =~ /(x|y)\n$/;
      return $buffer;
    }
    
    open my $fh, "<", $filename or die;
    my $nextRow = readDataSet($fh);
    
  2. 読み取りを行う匿名サブを構築します。Filehandle は、コンストラクター サブルーチンで 1 回だけ提供されます。これは少しオブジェクト指向です。

    sub newDataSetReader {
      my ($filehandle) = @_;
      return sub {
        my $buffer = '';
        local $/ = "\n";
        $buffer .= <$filehandle> until $buffer =~ /(x|y)\n$/;
        return $buffer;
      };
    }
    
    open my $fh, "<", $filename or die;
    my $reader = newDataSetReader($fh);
    my $nextRow = $reader->();
    

    私はこの最後の解決策を好みますが、複数のファイルから読み取る場合にのみ意味があります。

サブルーチンを介して読み取ると、デバッグ フックを簡単に挿入したり、データを事前にフィルター処理したりできます。たとえば、行をフィールドに分割し、単一の文字列ではなく配列を返すことができます。

于 2012-08-23T19:11:53.247 に答える