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+|\.+)表示一个或多个数字或一个或多个句点。但是你想要的是([\d.]+)这意味着一个或多个数字或句点。

捕获大小和项目也存在类似的问题。此外,您错误地使用了开始锚点 ( ^) 和结束锚点 ( $)。

你可以试试:

^\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 回答