in reply to Tagging the last elements
#!/usr/bin/perl use strict; use warnings; my @records; my %max; while (<DATA>) { my @fields = split; my ( $number, $name ) = ( $fields[3] =~ /^(\d+),(\w+)/ ); if ( ! $number or ! $name ) { warn "Line $.: unexpected input ignored: $_"; next; } $max{$name} = $number unless ( exists( $max{$name} ) and $max{$name} >= $number ); push @records, { name => $name, data => $_ }; } for my $rec ( @records ) { my $name = $rec->{name}; my $max = $max{$name}; my $flag = ( $max == 1 ) ? 'single' : 'end'; $rec->{data} =~ s/(\s)$max,$name,/$1$flag,$name,/; print $rec->{data}; } __DATA__ 62556 63635 y 1,andrew,JJ113954 63868 63897 h 1,morgan,JJ113955 68766 69005 j 2,morgan,JJ113955 81099 81630 y 1,flintoff,JJ113952 126185 126699 s 1,austin,JJ113956 135356 135449 3 1,peter,JJ113952 135588 136297 8 2,peter,JJ113952 158146 158367 i 3,peter,JJ113952 441474 441538 b 9,catherine,JJ029490 442666 442843 9 8,catherine,JJ029490 445778 445905 0 7,catherine,JJ029490 446059 446273 l 6,catherine,JJ029490 450319 450379 f 5,catherine,JJ029490
(updated to add a condition for skipping lines that don't match /\d+,\w+/ in fourth field-- it pays to be careful...)
In the for loop, the $rec->{data} =~ s/.../.../ will do nothing on the lines that don't contain the max value for a given name, because the regex won't match. For lines that contain a max value, the replacement will be either "single" or "end" depending on what the max value is.
In order to read from a file name that you put on the command line (i.e. in @ARGV) when you run the script, just remove DATA from while(<DATA>) (and leave off the __DATA__ section at the end) -- there's no need to explicitly open a file whose name is provided via @ARGV.
|
|---|