提取每第n个数字

时间:2011-02-23 14:20:19

标签: perl

我想从文件中提取每个第3个数字(42.034,41.630,40.158等) 见例子 -

42.034  13.749  28.463  41.630  12.627  28.412  40.158  12.173  30.831  26.823
12.596  32.191  26.366  13.332  32.938  25.289  12.810  32.419  23.949  13.329

使用perl脚本的任何建议?

谢谢, DAC

8 个答案:

答案 0 :(得分:8)

您可以将文件内容拆分为单独的数字,并使用modulo operator提取每个第3个数字:

my $contents = do { local $/; open my $fh, "file" or die $!; <$fh> };    
my @numbers = split /\s+/, $contents;

for (0..$#numbers) {
    $_ % 3 == 0 and print "$numbers[$_]\n";
}

答案 1 :(得分:4)

use strict;
use warnings;
use 5.010; ## for say
use List::MoreUtils qw/natatime/;

my @vals = qw/42.034  13.749  28.463  41.630  12.627  28.412  40.158  12.173  30.831 
26.823 12.596  32.191  26.366  13.332  32.938  25.289  12.810  32.419  23.949  13.329/;
my $it = natatime 3, @vals;
say while (($_) = $it->());

答案 2 :(得分:2)

这可能是指定它的最短方式。如果@list是您的号码列表

 @list[ grep { $_ % 3 == 0 } 0..$#list ]

答案 3 :(得分:2)

这是一个单行!

$ perl -lane 'print for grep {++$i % 3 == 1} @F' /path/to/your/input

-n为您提供逐行处理,-a自动分割以进行字段处理,$i(为了我们的目的有效地初始化为零)保持处理字段数的计数...

答案 4 :(得分:1)

此方法可以避免立即将整个文件读入内存:

use strict;

my @queue;

while (<>) {
    push @queue, / ( \d+ (?: \. \d* ) ? ) /gx;
    while (@queue >= 3) {
        my $third = (splice @queue, 0, 3)[2];
        print $third, "\n";  # Or do whatever with it.
    }
}

答案 5 :(得分:0)

如果文件中每行有10个数字,您可以使用:

perl -pe 's/([\d.]+) [\d.]+ [\d.]+/$1/g;' file

这不是一个干净的解决方案,但它应该“做好工作”。

答案 6 :(得分:0)

看起来这篇文章缺少一个没有读取整个文件并使用grep的解决方案。

#!/usr/bin/perl -w

use strict;

my $re = qr/-?\d+(?:\.\d*)/; # Insert a more precise regexp here
my $n = 3;

my $count = 0; 
while (<>) {
     my @res = grep { not $count++ % $n } m/($re)/go;
     print "@res\n";
};

答案 7 :(得分:0)

我相信你会发现这项工作符合规范,礼貌地行事,而且从不读取所需内容。

#!/usr/bin/env perl

use 5.010_001;

use strict;
use autodie;
use warnings qw[ FATAL all ];
use open     qw[ :std IO :utf8 ];

END { close STDOUT }

use Regexp::Common;
my $real_num_rx = $RE{num}{real};

my $left_edge_rx = qr{
    (?: (?<= \A              )  # or use \b
      | (?<= \p{White_Space} )  # or use \D
    )
}x;

my $right_edge_rx = qr{
    (?= \z                      # or use \b
      | \p{White_Space}         # or use \D
    )
}x;

my $a_number_rx = $left_edge_rx
                . $real_num_rx
                . $right_edge_rx
                ;

if (-t STDIN && @ARGV == 0) {
    warn "$0: reading numbers from stdin,"
       . " type ^D to end, ^C to kill\n";
}


$/ = " ";
my $count = 0;
while (<>) {
    while (/($a_number_rx)/g) {
        say $1 if $count++ % 3 == 0;
    }
}