0

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";
5
  • 2
    You need to trim down your code and create a Short, Self Contained, Correct (Compilable), Example. Commented Mar 27, 2013 at 5:16
  • 1
    Post the code relevant to question. Where are those print array statements? Commented Mar 27, 2013 at 5:17
  • Edited example, and re-phrased question. My apologies for initial mistakes. Commented Mar 27, 2013 at 5:30
  • Your continued mistakes. You do not print either $dev_parts or $label_parts. Also, those are not lengths, they are used as array indexes. Also, they are used as array indexes in the same array @parts. So why would they not print the same values? Also, you do not assign anything to $dev_length2 or $label_length2, which means that without warnings turned on they are silently converted to 0. Commented Mar 27, 2013 at 5:46
  • 2
    Here's my suggestion: Add use warnings and fix the warnings that appear. Add use Data::Dumper and add print Dumper \@parts etc statements for variables to see what they contain. Commented Mar 27, 2013 at 5:49

2 Answers 2

1

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);
Sign up to request clarification or add additional context in comments.

Comments

0

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>) {

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.