开发者

extract every nth number

i want to extract every 3rd number ( 42.034 , 41.630 , 40.158 as so on ) from the file see e开发者_JAVA技巧xample-

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

Any suggestions using perl script ?

Thanks, dac


You can split file's contents to separate numbers and use the modulo operator to extract every 3rd number:

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";
}


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->());


This is probably the shortest way to specify that. If @list is your list of numbers

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


It's a one-liner!

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

-n gives you line-by-line processing, -a autosplitting for field processing, and $i (effectively initialized to zero for our purposes) keeps count of the number of fields processed...


This method avoids reading the entire file into memory at once:

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.
    }
}


If the file has 10 numbers in every line you can use this:

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

It's not a clean solution but it should "do the job".


Looks like this post lacked a solution that didn't read the whole file and used 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";
};


I believe you’ll find that this work per spec, behaves politely, and never reads in more than it needs to.

#!/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;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜