【问题标题】:While loop ends prematurely on a regexWhile 循环在正则表达式上过早结束
【发布时间】:2017-10-27 00:17:11
【问题描述】:

我正在通过 ActivePerl 运行以下 Perl 脚本以从文本中提取时间和 ID 数值。 出于某种原因,while 循环在检查文本的第一行后结束。

这是我使用的 Perl 代码:

#!/usr/bin/perl -w
$inputfile = "nr_raw.txt";
$outputfile = "results.txt";  #create this output file (it will be created automatically in the current folder)
open (OUTPUTFILEHANDLE, "> $outputfile") || die "I can't find or open $file: error $!\n";
open (INPUTFILEHANDLE, $inputfile) || die "I can't find or open $file!\n";
$_=<INPUTFILEHANDLE>;
while (/{.*?"timestamp":(\d+).*?"accountId":(\d+).*?}\n/sg)
{
$info="timestamp: $1 accountID: $2";
print "$info \n";
print OUTPUTFILEHANDLE $info ;
}
close OUTPUTFILEHANDLE;

nr_raw.txt:(第三行没有accountId条目)

{"eventType":"alarm","timestamp":1508845227478,...,"accountId":1275676,"Version":"1.3",....}
{"eventType":"alarm","timestamp":1508845166740,...,"accountId":1274721,"Version":"1.1",....}
{"eventType":"alarm","timestamp":1508845187479,....,..................,"Version":"1.1",....}
{"eventType":"alarm","timestamp":1508845166980,...,"accountId":1347376,"Version":"1.2",....}

results.txt:(没有别的)

timestamp 1508845227478 account ID1275676

【问题讨论】:

  • perl 5.0 发布已经23年了。您现在可以use strict;use warnings;
  • 您的代码只从文件中读取一行。
  • $_=; # 只读取文件的第一行
  • 有道理,谢谢你的澄清。我在其他文本文件上使用了类似的脚本,但在这种情况下它可能起作用,因为整个文本可能是一行(没有 LF/CR)

标签: regex perl


【解决方案1】:

你只读过一行!

#!/usr/bin/perl

use strict;
use warnings;
use Cpanel::JSON::XS qw( );

my $parser = Cpanel::JSON::XS->new();

while (<>) {
    my $rec = $parser->decode($_);
    print("timestamp: $rec->{timestamp} accountID: $rec->{accountId}\n")
        if $rec->{accountId};
}

用法:

script nr_raw.txt >results.txt

【讨论】:

  • 谢谢。我将安装 Cpanel::JSON::XS 模块并使用它!
【解决方案2】:

将正则表达式放在 if 语句中,并让 while 循环读取每一行。

    #!/usr/bin/env perl
    use strict;
    use warnings;
    use autodie; # See http://perldoc.perl.org/autodie.html

    my $inputfile = "nr_raw.txt";
    my $outputfile = "results.txt";  #create this output file (it will be created automatically in the current folder)

    # autodie handles errors automatically.
    open my $out_fh, '>', $outputfile;
    open my $in_fh, '<', $inputfile;

    while( my $line = <$in_fh> ){
        if( $line =~ /{.*?"timestamp":(\d+).*?"accountId":(\d+).*?}\n/sg ){
            my $info = "timestamp: $1 accountID: $2";

            print "$info \n";
            print $out_fh $info ;
        }
    }

# autodie handles errors automatically.
close $out_fh;
close $in_fh;

【讨论】:

  • 我的工作就像一个魅力,谢谢。现在我意识到这正是我应该做的。我很困惑,因为相同的脚本适用于其他文本文件(可能是因为它们只是一个 lin,没有 LF/CR)。再次感谢您!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-16
  • 2016-01-22
  • 2011-12-05
  • 1970-01-01
相关资源
最近更新 更多