user1739860
user1739860

Reputation:

Printing array in Perl

I currently have my Perl script to read fstab files, split them up by column and search for which word in each column is the longest to display it. All that works peachy (I think), the problem I'm having is that it keeps printing out the same length for every line which is not true. Example $dev_parts prints 24, and $labe_parts prints 24 and so on...

below is my code.

  #!/usr/bin/perl
  use strict;

  print "Enter file name: \n";
  my $file_name = <STDIN>;
  open(IN, "$file_name");

  my @parts = split( /\s+/, $file_name);
  foreach my $usr_file (<IN>) {
      chomp($usr_file);
      @parts = split( /\s+/, $usr_file);
      push(@dev, $parts[0]);
      push(@label, $parts[1]);
      push(@tmpfs, $parts[2]);
      push(@devpts, $parts[3]);
      push(@sysfs, $parts[4]);
      push(@proc, $parts[5]);
  }

  foreach  $dev_parts (@dev) {
      $dev_length1 = length ($parts[$dev_parts]);
      if ( $dev_length1 > $dev_length2) {
              $dev_length2 = $dev_length1;
      }
  }
  print "The longest word in the first line is: $dev_length2 \n";

  foreach  $label_parts (@label) {
      $label_length1 = length($parts[$label_parts]);
      if ($label_length1 > $label_length2) {
              $label_length2 = $label_length1;
      }
  }
  print "The longest word in the first line is: $label_length2 \n";

Upvotes: 0

Views: 198

Answers (2)

user1919238
user1919238

Reputation:

You have a mistake here:

foreach  $dev_parts (@dev) {
     $dev_length1 = length ($parts[$dev_parts]);

As I understand it, you are looking for the longest element in @dev. However, you take the length of an element from the @parts array. This array is always set to whatever the last line of the file is. So you are looking at each element in the last line of the file, rather than each element of the appropriate column.

You just need to take length($dev_parts) instead.

Incidentally, here is a simpler way to find the longest length in an array:

use List::Util qw/max/; #Core module, always available.

my $longest_dev = max map {length} @dev;

A few other comments on your code:

use strict; is good. You should also use warnings;. It will help you catch silly mistakes in your code.

You ought to check for errors whenever you open a file:

open(IN, $file_name) or die "Failed to open $file_name: $!";

Better yet, use the preferred open syntax with a lexical filehandle:

open(my $in_file, '<', $file_name) or die "Failed to open $file_name: $!";
...
while (<$in_file>) { 

I'm not sure what you are trying to do here:

my @parts = split( /\s+/, $file_name);

You are splitting the file name by white space, but you don't use that for anything. And then you re-use the same array to hold the lines later.

A while loop is preferred to foreach when you go through lines of a file. It saves memory because it doesn't read the whole file into memory first (and it is otherwise exactly the same).

while (my $usr_file = <IN>) {

Upvotes: 0

user966588
user966588

Reputation:

This is how your code should be

  #!/usr/bin/perl
  use strict;
  use warnings;
  use Data::Dumper;

  print "Enter file name: \n";
  my $file_name = <STDIN>;
  chomp($file_name);
  open(FILE, "$file_name") or die $!;

  my %colhash;
  while (<FILE>) {
      my $col=0;
      my @parts = split /\s+/;

      map { my $len = length($_);
        $col++;
        if($colhash{$col} < $len ){ 
            $colhash{$col} = $len;    # store the longest word length for each column
        } 
    } @parts;      
  }

print Dumper(\%colhash);

Upvotes: 1

Related Questions