2

Perl で正規表現を N+1 回試行した後: 次の問題があります: これを取得する必要があります:

  232310..1.3      3213   2.4  "$250 For My jacket" (2012)

私はそれを取得しようとしています:

if ( $line=~m/^\s+(\d+|\.+)\s+(\d+)\s+(\d+|\.+)\s+(\^"&(\w*|\s*|\D*)"$)\s*\((\d+)\s*/){
        $ID=$1;
        $Amount=$2;
        $Size=$3;
        $Item=$4;
        $Year=$5;

それは動作しません

4

3 に答える 3

6

(\d+|\.+)1 つ以上の数字または 1 つ以上のピリオドを意味します。しかし、必要なのは([\d.]+)、1 つまたは複数の数字またはピリオドを意味することです。

サイズとアイテムのキャプチャでも同様の問題が発生します。^また、開始アンカー ( ) と終了アンカー ( )を誤って使用しています$

あなたが試すことができます:

^\s+([\d.]+)\s+(\d+)\s+([\d.]+)\s+"([^"]+)"\s*\((\d+)\s*

見る

于 2012-04-16T08:44:40.783 に答える
2

4行目のエントリがすべて引用されている場合、codaddictのソリューションは問題ありません。別のアプローチは、CSVパーサー(おそらく最初にCPANからインストールする必要があります)を使用することです。たとえば、次のようになります。

#!/usr/bin/env perl

use strict;
use warnings;

use Text::CSV_XS;

my $csvr = new Text::CSV_XS({
  sep_char => ' ',
  eol => $/
});

my $csvw = new Text::CSV_XS({
  sep_char => ',',
  eol => $/
});

$csvw->print( *STDOUT, [ qw(ID Amount Size Item Year) ]);

while (my $row = $csvr->getline(*ARGV))
{
  $csvw->print( *STDOUT, [ grep { /./ } @$row ] );
}

}

入力が与えられたとき

232310..1.3      3213   2.4  "$250 For My jacket" (2012)

これにより、次のものが生成されます。

232310..1.3,3213,2.4,"$250 For My jacket",(2012)

さらなるステップは、を使用DBD::CSVすることです。これにより、入力ファイルに対してSQLクエリを実行できます。

于 2012-04-17T12:35:32.343 に答える
1

codaddictと同じ修正ですが、正規表現を読みやすくする方法を示しています。「x」オプションは、より長い正規表現や複数のキャプチャ変数に非常に役立ちます。

(私はこれをコメントとして投稿したでしょうが、限られたフォーマットオプションのために)

my ( $id, $amount, $size, $item, $year ) = $line =~ m{
    ^
    \s+
    ([\d.]+)        # field 1, e.g. 232310..1.3
    \s+
    (\d+)           # field 2, e.g. 3213
    \s+
    ([\d.]+)        # field 3, e.g. 2.4
    \s+
    "([^"]+)"       # field 4, e.g. "$250 For My jacket"
    \s*
    \((\d+)\)       # field 5, e.g. (2012)
    \s*
}x or die "Line does not match!";  # always check that a regex actually succeeded!
于 2012-04-17T12:01:42.713 に答える