Reputation: 5927
I'm Trying to print columns from data by using index key value in the outer part of a foreach loop.
my @col;
foreach(<DATA>){
@x = split(' ',$_);
@xz = ($x[0],$x[1],$x[2]) ;
#print "$x[0]\n"; This is working but i'm not expect this.
push(@col,@xz);
}
print "$col[0]\n";
__DATA__
7 2 3
3 2 8
6 7 2
I expect the output is
7 3 6
How can i do it?
Upvotes: 1
Views: 126
Reputation: 107040
Always use use strict;
and use warnings;
!!
You have a couple of issues:
push( @col, @xz );
In this case, you're losing your information in @xz
array. After this loop, you end up with a single array that looks like this:
@col = ( 7, 2, 3, 3, 2, 8, 6, 7, 2);
So, when you print:
print "$col[0]\n";
You get that zeroth element: 7.
We can preserve the structure of the data by using a reference:
#! /usr/bin/env perl
#
use strict; # Lets you know when you misspell variable names
use warnings; # Warns of issues (using undefined variables
use feature qw(say);
use Data::Dumper;
my @columns;
for my $data ( <DATA> ) {
my @data_list = split /\s+/, $data;
push @columns, \@data_list;
}
say Dumper \@columns;
__DATA__
7 2 3
3 2 8
6 7 2
Here you see I've included Data::Dumper to print out the structure of @columns
:
$VAR1 = [
[
'7',
'2',
'3'
],
[
'3',
'2',
'8'
],
[
'6',
'7',
'2'
]
];
As you can see, each entry in the @columns
array is now another array. However, printing out $columns[0]
array reference isn't going to print what you want. Instead, it's going to print the zeroth array reference: 7, 2, 3, and not the zeroth element of each array reference: 7, 3, 6.
To do that, we need a subroutine that will go through @columns
and print out the the zeroth entry of each of the arrays. Here I'm creating a subroutine called fetch_index
that will fetch the passed index of the passed array:
#! /usr/bin/env perl
#
use strict; # Lets you know when you misspell variable names
use warnings; # Warns of issues (using undefined variables
use feature qw(say);
use Data::Dumper;
my @columns;
for my $data ( <DATA> ) {
my @data_list = split /\s*/, $data;
push @columns, \@data_list;
}
say join ", ", fetch_index( 0, @columns );
sub fetch_index {
my $entry = shift; #Entry you want from all arrays
my @array = @_;
my @values;
for my $array_ref ( @array ) {
push @values, ${array_ref}->[$entry];
}
return @values;
}
__DATA__
7 2 3
3 2 8
6 7 2
The subroutine merely goes through each array reference I've stored in my array, and fetched the $entry
value from that array reference. I push those into my @values
array and return that.
Upvotes: 3
Reputation: 7
perl -a -F' ' -ne 'print "$F[0]\n";' data.txt
here you $F[0] is field you can change it accordingly you will get the expected output
Upvotes: 0
Reputation: 1068
my @col;
while (<DATA>) {
push @col, (split ' ')[0];
# push @col, /(\S+)/; # split alternative
}
print "@col\n";
__DATA__
7 2 3
3 2 8
6 7 2
output
7 3 6
Upvotes: 2
Reputation: 6378
Once you've absorbed the information about anonymous arrays and references in the other excellent posts here, you can start to have fun. e.g. you can often get a one liner approach to work:
perl -nE 'say [split]->[1] ' col_data.txt
would loop (-n
creates an implicit while(){}
loop) through the data in col_data.txt
, split
the topic variable ($_
) creating a series of anonymous arrays from each row and then print the second element, or "column" for example.
You can use the autosplit command line option (-a
) to split each row into an array called @F
(mnemonic: "F
" for "Field"). In later versions of perl
, the -a
implies the implicit while
loop (-n
):
perl -anE 'say $F[1] ' col_data.txt
would be the equivalent of the previous command - printing the second column:
output:
2
2
7
There is a famous and short perl workalike for cut
that is a more featureful variaton on this theme, and there is this Perl Monks thread.
Upvotes: 0
Reputation: 5236
You were pretty close I think. This is what I did (edited to reflect comments from @Borodin):
use strict;
use warnings;
sub getColumn {
my ($data, $col) = @_;
my @output = map $_->[$col], @{$data};
return @output;
}
my @data;
while (<DATA>){
push(@data, [split(' ',$_)]);
}
print join(' ', getColumn(\@data, 0), "\n");
print join(' ', getColumn(\@data, 1), "\n");
print join(' ', getColumn(\@data, 2), "\n");
__DATA__
7 2 3
3 2 8
6 7 2
That subroutine getColumn
should let you retrieve any arbitrary column. When I ran it with your data I got this for output:
7 3 6
2 2 7
3 8 2
Upvotes: -1