Home: Perl Programming Help: Beginner:
Need help printing out only certain items in a file



AndrewF
Novice

Jul 6, 2013, 1:01 PM


Views: 1777
Need help printing out only certain items in a file

Hey guys, I just started learning Perl and am now tasked with something quite challenging. I have been given a file with text, here it is:
Header1|Header2|Header3|Header4
Microsoft|MSFT|UN|85
Oracle|ORCL|UN|10.0
Johnson & Johnson|JNJ|US|5

I have to make 2 arrays, one for the second group of text (MSFT, ORCL, JNJ) and another for the third group of text (UN,UN,US)print those arrays filled with only that text and nothing else. Here is what I have so far on it, but my filtereing on grep isnt working the way I'd like. Any help would be much appreciated!

open (FILE, "practice.txt");
my @array = <FILE>;
my @spaced = split (/|/, @array);
my @sorted = grep {$_ =~ "[A-Z]"} @spaced;
print @spaced;
close(FILE);
the files name is practice.txt


hwnd
User

Jul 6, 2013, 1:44 PM


Views: 1762
Re: [AndrewF] Need help printing out only certain items in a file

You should always use 'strict' and 'warnings' to catch errors before they get out of hand. And use proper error handling.


Code
use strict; 
use warnings;



On your split, it's only going to split characters because you need to back reference your pipe. Also grep is useless in this case.


Code
split(/\|/, @array);



Here's an example to get you started.


Code
use strict; 
use warnings;

my @array1;
my @array2;

open my $fh, '<', 'practice.txt' or die "failed $!";
while (<$fh>) {
next if $. == 1; # skip headers
push @array1, (split /\|/)[1]; # split 1st columns and push in array1
push @array2, (split /\|/)[2]; # split 2nd columns and push in array2
}
close $fh;

print "$_\n" foreach @array1; # same for array2



Zhris
Enthusiast

Jul 6, 2013, 1:51 PM


Views: 1759
Re: [hwnd] Need help printing out only certain items in a file

Hi,

Just an improvement. It is probably nicer to split just once, possibly inside the while:


Code
while ( my @row = split /\|/, <$fh> )


Chris


2teez
Novice

Jul 6, 2013, 1:51 PM


Views: 1758
Re: [AndrewF] Need help printing out only certain items in a file

If I may first comment on your code:
There are a number of things that are good practice using Perl.
1. You should use 3 - argument of open function in Perl,
2. Use a lexical scope file handles,
3. Check the return of the both "open" and "close" function or you use "autodie".
All of that is demonstrated below:

Code
 open my $fh,' <', 'practice.txt' or die "can't open file: $!"; 
...
close $fh or die "can't close file: $!";


That been said, this is one way of going what you wanted:
After opening the file, you could step through the file a line at a time, split on "/" and get the value you wanted.
Make an ARRAY of ARRAY and store this values.
Then you can print out all the values you want.

Please let me give you a head up with a little code that does what I think you want.


Code
use warnings; 
use strict;
use Data::Dumper;

<DATA>; #remove the heading if not needed

my @data;
my $counter;

while(<DATA>){
chomp;
$counter = 0;
for ((split/\|/,$_)[1,2]){
push @{$data[$counter++]},$_;
}
}

print Dumper \@data;
#OR
print join $/=> map @$_ => @data;

__DATA__
Header1|Header2|Header3|Header4
Microsoft|MSFT|UN|85
Oracle|ORCL|UN|10.0
Johnson & Johnson|JNJ|US|5


This produces:

Code
$VAR1 = [ 
[
'MSFT',
'ORCL',
'JNJ'
],
[
'UN',
'UN',
'US'
]
];

MSFT
ORCL
JNJ
UN
UN
US


For ARRAY of ARRAY, please read up http://perldoc.perl.org/perldsc.html#ARRAYS-OF-ARRAYS


(This post was edited by 2teez on Jul 6, 2013, 2:07 PM)


AndrewF
Novice

Jul 6, 2013, 3:48 PM


Views: 1740
Re: [AndrewF] Need help printing out only certain items in a file

Ahhh yes, Thank you all so much you have helped immensly!


Laurent_R
Veteran / Moderator

Jul 7, 2013, 2:09 AM


Views: 1724
Re: [AndrewF] Need help printing out only certain items in a file

This session under the Perl debugger shows another possible way to do what you need:


Code
  DB<1>  $c = "Microsoft|MSFT|UN|85 " 

DB<2> push @d, [(split /\|/, $c)[1,2]]

DB<3> $c = "Oracle|ORCL|UN|10.0"

DB<4> push @d, [(split /\|/, $c)[1,2]]

DB<5> x @d
0 ARRAY(0x80359bd0)
0 'MSFT'
1 'UN'
1 ARRAY(0x80356018)
0 'ORCL'
1 'UN'
DB<6> print "$_->[0]\n" for @d
MSFT
ORCL

DB<7> print "$_->[1]\n" for @d
UN
UN


Looking back at your original requirement, this solution does not really create the two arrays (it will create an array of n arrays if the file has n lines). So, if you really need to create these arrays you can add one line to create it and then print the newly created array:

Code
  DB<8> @f = map {$_->[0]} @d 

DB<9> x @f
0 'MSFT'
1 'ORCL'
DB<10> print join "\n", @f
MSFT
ORCL



(This post was edited by Laurent_R on Jul 7, 2013, 2:10 AM)