Perl-从逗号分隔行获取值

Perl-从逗号分隔行获取值,perl,Perl,我正试图重写一个perl文件解析器。 这是一个动态解析器,我需要从逗号分隔的行中提取一个值 我想从中获取一个值的行如下所示: ENTRYNAME-8,44544,99955,52,156,15:16:16,15:19:16 (这是每个解析文件中唯一以ENTRYNAME-开头的一行。-之后的所有内容都会对每个正在解析的文件进行更改) 我想要第二个逗号后面的值。(99955在上面的示例中) 我尝试了以下方法,但没有任何运气: if (/ ENTRYNAME-\((.*)\,(.*)\,(.*)\)

我正试图重写一个perl文件解析器。 这是一个动态解析器,我需要从逗号分隔的行中提取一个值

我想从中获取一个值的行如下所示:

ENTRYNAME-8,44544,99955,52,156,15:16:16,15:19:16
(这是每个解析文件中唯一以
ENTRYNAME-
开头的一行。
-
之后的所有内容都会对每个正在解析的文件进行更改)

我想要第二个逗号后面的值。(
99955
在上面的示例中)

我尝试了以下方法,但没有任何运气:

if (/ ENTRYNAME-\((.*)\,(.*)\,(.*)\)/ ) 
{
    $entry_nr = $3;
    print "entry number = $entry_nr";
    next;
}

将其拆分为一个数组并直接寻址:

my @a = split /,/, $_;
print $a[2];

这里发生的事情是,$\中的任何内容(通常来自(@allmylines){-loop)将在每次出现
时被拆分,并将它们全部放入一个数组(
@a
)并删除
。然后可以寻址数组中的字段,第一个字段从0开始。因此,如果要寻址第三个字段,请使用
$a[2]
检索第三项。

问题是,您的第一个捕获字符串
*
是贪婪的,因此它将消耗您的所有字符串。然后,它将回溯以查找两个逗号,并作为从末尾匹配的结果

此外:

  • 由于某种奇怪的原因,您正在匹配文字括号
    \(
    ),因为您没有这样的括号,所以这些括号永远不会匹配
  • 您不需要转义逗号
    \,
  • 正则表达式
    /ENTRY…
    中不能有随机空格,除非目标字符串中有随机空格
  • 您不需要捕获不打算使用的字符串
一个简单的解决方法是使用更严格的捕获组(包括以上几点):

这将捕获到
$1


正如mpapec在评论中指出的那样,您可能希望使用
Text::CSV
解析CSV数据。这样会更安全。如果您的数据足够简单,此解决方案就可以了。

只要有可能,将解析与处理和验证数据分开

在这种情况下,如果您有逗号分隔的值,请继续并分隔这些值。然后担心筛选数据。是否使用
Text::CSV
进行解析是一个单独的问题,尽管可能是一个好主意

use strict;
use warnings;

while (<DATA>) {
    chomp;
    my @cols = split ',';

    if ($cols[0] =~ /^ENTRYNAME/) {
        print $cols[2], "\n";
    }
}

__DATA__
ENTRYNAME-8,44544,99955,52,156,15:16:16,15:19:16

最好使用
Text::CSV
,或者至少在分隔符上拆分行,
split/,/
这些CSV行是否会被引用并在字符串中嵌入“,”?@Brett_Schneider如果每行都引用了带有嵌入逗号的字符串呢?@octopusgrabbus在问题中没有这样说,因此我认为花费时间c没有意义ontemplating它。@Victor我已经考虑过了,因此将我的答案扩展到了这一点。谢谢!这最终使所有的问题都解决了。我本来会使用Text::CSV,但输入数据并不简单。@user2837756如果你有合适的CSV数据,你可能只应该使用
Text::CSV
。正则表达式是一个可行的小规模解决方案或者是一个变化有限的有限数据集。但是您可能应该添加一些安全保护和错误报告,以防遇到意外的变化。
use strict;
use warnings;

while (<DATA>) {
    chomp;
    my @cols = split ',';

    if ($cols[0] =~ /^ENTRYNAME/) {
        print $cols[2], "\n";
    }
}

__DATA__
ENTRYNAME-8,44544,99955,52,156,15:16:16,15:19:16
99955