0

I'm trying to read each record of a text file, one line at a time, and place it into an array. Text file looks like this...

 root:x:0:0:root:/root:/bin/bash
 bin:x:1:1:bin:/bin:/sbin/nologin
 ETC

Then access a specific element of the array, and use an if statement to see if it meets certain requirements. My code won't compile, it just closes immediately, I'm stuck and need a push in the right direction. Heres what I have so far...

open (FILEHANDLE1, "text.old") || die "Can't open file named text.old: $!";

open (FILEHANDLE2, ">text.new") || die "Can't create file named text.new: $!\n";

while ($_ = <FILEHANDLE1>)
{
@array = split (/:/, <FILEHANDLE1>);
if ($array[2] eq "0")
    {
    print "$array[2] Superuser Account\n";
    }

close (FILEHANDLE2) || die "Can't close file named text.new: $!\n";

close (FILEHANDLE1) || die "Can't close the file named text.old: $!";
2
  • You're not writing anything out to text.new. Commented Dec 10, 2013 at 4:48
  • My bad, I will be doing that later. Thanks Kenosis. Commented Dec 10, 2013 at 5:04

1 Answer 1

3

This while loop has no closing brace:

while ($_ = <FILEHANDLE1>)
{
@array = split (/:/, <FILEHANDLE1>);
if ($array[2] eq "0")
    {
    print "$array[2] Superuser Account\n";
    }

Secondly, you really want to write this as:

while (<FILEHANDLE1>)
{
    chomp;
    my @array = split /:/;
    if ($array[2] eq "0")
    {
        print "$array[2] Superuser Account\n";
    }
}

The chomp isn't strictly necessary, but it'll avoid you getting strange results with a newline hanging out in the "shell" field of the password file you're parsing, if you eventually need to process the shell.

One last stylistic suggestion, as you're still learning perl: You should try to avoid using the old two argument open, and instead use the newer three argument open. That is, instead of this:

open (FILEHANDLE2, ">text.new") || die "Can't create file named text.new: $!\n";

You should instead use the three argument form:

open (FILEHANDLE2, ">", "text.new") || die "Can't create file named text.new: $!\n";

For this particular example it doesn't make much difference. The three-argument form is safer, though, when the filename arrives in a variable.

You might also consider getting into the habit of using lexical filehandles.:

open my $filehandle1, "<", "text.old" or die "Can't open file named text.old: $!\n";
open my $filehandle2, ">", "text.new" or die "Can't create file named text.new: $!\n";

while (<$filehandle1>)
{
    chomp;
    my @array = split /:/;
    if ($array[2] eq "0")
    {
        print "$array[2] Superuser Account\n";
    }
}

close $filehandle2 or die "Can't close file named text.new: $!\n";
close $filehandle1 or die "Can't close the file named text.old: $!\n";

The advantage of lexical filehandles is that they stay local to whatever scope they're declared. This makes it easier to deal with files locally in a subroutine, for example.

I noticed that you weren't doing anything with the second file yet. (FILEHANDLE2 in your original code.) I assume that code's coming once you get the basics working. :-)

Sign up to request clarification or add additional context in comments.

3 Comments

Always use strict; use warnings;
Your right, I'm very new to perl. This is great advice I'll be able to use for later scripts, much more efficient use of code. My script is compiling great now. Thanks Joe Z.
@LMN0321 : I figured you were still new to the language. If you develop the right habits early, it'll make your experience with the language much nicer. :-)

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.