新しい改行が含まれるテキストを含む CSV ファイルがあります。例えば
1,b,hello
world,x
2,a,hello
mars,y
一度にすべて読み取るために、 $/ 特殊変数に正規表現を指定したいと思います。どうすればそれができるかについて何か提案はありますか?
私の考えでは、特殊変数に "(x|y)\n" のようなものを入れると、行が x または y で終わり、新しい行が続く場合をキャプチャする必要があります。
ありがとう
新しい改行が含まれるテキストを含む CSV ファイルがあります。例えば
1,b,hello
world,x
2,a,hello
mars,y
一度にすべて読み取るために、 $/ 特殊変数に正規表現を指定したいと思います。どうすればそれができるかについて何か提案はありますか?
私の考えでは、特殊変数に "(x|y)\n" のようなものを入れると、行が x または y で終わり、新しい行が続く場合をキャプチャする必要があります。
ありがとう
$/ に正規表現を使用することはできません。ただし、ファイルが大きすぎない場合は、全体をスカラーに読み取り、正規表現で分割できます。
@records = split /(x|y)\n/, $data;
このようなファイルをレコードに分割する一般的な方法はありません。ファイルの行が現在のレコードに近いのか、それとも新しいレコードの始まりなのかを判断することは不可能だからです。
ただし、仮定できる場合
レコードには常に同じ数のフィールドがあります
フィールド内のデータにカンマが含まれていない
レコードの最後のフィールドが複数行に分割されることはありません
次に、十分な数のフィールドが得られるまで、ファイルから行を単純に蓄積できます
このプログラムは原理を示しています。
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
独自のサブを作成して、一度に 1 つのデータセットを読み取ることができます。
sub readDataSet {
my $buffer = '';
local $/ = "\n";
$buffer .= <STDIN> until $buffer =~ /(x|y)\n$/;
return $buffer;
}
my $nextRow = readDataSet();
これにより、行全体が返されます。あなたの正規表現は定数部分で終わるので、私はこれを行うことができます。このサブにはいくつかのバリエーションがあります。
任意のファイルハンドルから読み取ります:
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);
読み取りを行う匿名サブを構築します。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->();
私はこの最後の解決策を好みますが、複数のファイルから読み取る場合にのみ意味があります。
サブルーチンを介して読み取ると、デバッグ フックを簡単に挿入したり、データを事前にフィルター処理したりできます。たとえば、行をフィールドに分割し、単一の文字列ではなく配列を返すことができます。