つまり、漠然と CSV ファイルに似ているものがありますが、そうではありません。あなたができることの1つは、ギャップを埋めてから通常どおりに処理することです.他の誰もがこれを行う方法を提案しています. 他にできることは、肩をすくめてそのまま CSV 以外のものとして処理することです。
ここでは、行の先頭に ID があり、その後にコンマが続きます。
/^(\d+),/;
そして、すべての後にコンマが続きます:
/^(\d+),(.+),/
そして、価格、その後に行末が続きます:
/^(\d+),(.+),(\d+(?:\.\d+)?)$/
そして、はい、それ(.+),
はあなたが埋め込まれたコンマで望むように真ん中に働きます。 +
貪欲なので、これは右から左にバックトラックして、残りのパターンが一致する最初のポイントを見つけます。
全体:
#! /usr/bin/env perl
use common::sense;
while (<DATA>) {
next unless /^(\d+),(.+),(\d+(?:\.\d+)?)$/;
say "ID: $1";
say "Description: $2";
say "Price: $3";
say "----"
}
__DATA__
ID,Description,Price
1234,Good Part,1.23
2345,This is.ok,2.34
3456,Bad Part,with a comma,4.56
そして、少しきれいです (名前は名前よりも長いですが...):
#! /usr/bin/env perl
use common::sense;
while (chomp($_ = <DATA>)) {
next if /
^ID,Description,Price\z # allow only this header
| ^\s*\z # and blank lines
| ^\s*\# # and lines containing only a comment
/xi;
/^(?<ID> \d+),
(?<Description> .+),
(?<Price> \d+(?:\.\d+)?)
\z/x or die "Invalid line: $_";
say "$_: $+{$_}" for qw(ID Description Price);
say "----";
}
__DATA__
ID,Description,Price
1234,Good Part,1.23
2345,This is.ok,2.34
# why do we allow this again?
id,description,price
3456,Bad Part,with a comma,4.56
両方の出力:
ID: 1234
Description: Good Part
Price: 1.23
----
ID: 2345
Description: This is.ok
Price: 2.34
----
ID: 3456
Description: Bad Part,with a comma
Price: 4.56
----
ええ、わずかに異なる notCSV に合わせてこの正規表現を変更する必要がありますが、gap-closer も変更する必要があります。これが notCSV が悪い理由です。