Problem with useless use error message

D

delfuego

Hello,

I am trying to write a simple Perl program to do the following:
Open /etc/passwd for read, create an output file in cwd for append,
cut the fields 1,3-4,6 from /etc/passwd and redirect that output to
the output file password, then close the two file handles for the
input and output files.

Here is the code:

#!/usr/bin/perl -w
#
my $FIN;
my $FOUT;
#
open ($FIN, "</etc/passwd") or die "Cannot open input file.\n";
open ($FOUT, ">>password") or die "Cannot open output file.\n";
#
while ($myline = <$FIN>) {
readline($FIN);
$myline=$printable;
print($FOUT,$printable,"\n");
i $myline = chop($myline = `cut -d: -f1,3-4,6`);
}
#
close ($FIN);
close ($FOUT);
#

Here is the error message:

[root@localhost james]# ./program.pl
Use of uninitialized value in print at ./program.pl line 12, <$FIN>
line 2.
GLOB(0x804ca88)

[root@localhost james]#


Thank you for your help.

James
 
A

A. Sinan Unur

(e-mail address removed) (delfuego) wrote in
Hello,

I am trying to write a simple Perl program to do the following:
Open /etc/passwd for read, create an output file in cwd for append,
cut the fields 1,3-4,6 from /etc/passwd and redirect that output to
the output file password, then close the two file handles for the
input and output files.

Here is the code:

#!/usr/bin/perl -w

use strict;
use warnings;

If you haven't done so already, please read the posting guidelines posted
here regularly.
my $FIN;
my $FOUT;
open ($FIN, "</etc/passwd") or die "Cannot open input file.\n";
open ($FOUT, ">>password") or die "Cannot open output file.\n";

I recommend using the 3 argument form of open. You also don't need to
declare $FIN and $FOUT separately. Finally, it is useful to report the
actual reason open failed:

open my $FIN, '<', '/etc/passwd'
or die "Cannot open '/etc/passwd': $!";

open my $FOUT, '>>', 'password'
or die "Cannot open 'password': $!";
while ($myline = <$FIN>) {

while(my $myline = <$FIN>) {

OK, so you have read a line from $FIN.
readline($FIN);

Now, you read another line and discard it.
$myline=$printable;

But this is the best. You now replace the contents of the line you had
earlier managed to read and store in $myline with the contents of
$printable. However, $printable is undef at this point. If you had used
strict, you would have caught this error.
print($FOUT,$printable,"\n");

Now that you have nuked $myline you attempt to output $printable to $FOUT.
You might want to check

perldoc -f print

because this will never output aything to $FOUT.
i $myline = chop($myline = `cut -d: -f1,3-4,6`);

Ahem, what is that 'i' up there. Oh, I see, you did not actually post the
code you ran on your system. Don't do that.

So, now you are over-writing the line you had stored in $myline with the
return value of the chop call. Do you know what chop returns? I have a
feeling you don't. You can look it up:

perldoc -f chop

[root@localhost james]# ./program.pl
Use of uninitialized value in print at ./program.pl line 12, <$FIN>
line 2.
GLOB(0x804ca88)

perl has just told you everything I said above.
[root@localhost james]#

Are you sure you want to mess with your system's crucial files while you
are logged in as root?
Thank you for your help.

You are welcome.

Sinan.
 
T

Tad McClellan

delfuego said:
I am trying to write a simple Perl program to do the following:
Open /etc/passwd for read, create an output file in cwd for append,
cut the fields 1,3-4,6 from /etc/passwd and redirect that output to
the output file password, then close the two file handles for the
input and output files.


Here is a complete Perl program that does that:

perl -lne 'print join ":", (split /:/)[0,2,3,5]' /etc/passwd >>password

[root@localhost james]# ./program.pl


Yikes!

You shouldn't do things as root unless the thing *requires* that
you be root.

You do not need to be root to do what you describe above, so don't
be root when you are doing the above.
 
D

delfuego

A. Sinan Unur said:
(e-mail address removed) (delfuego) wrote in
Hello,

I am trying to write a simple Perl program to do the following:
Open /etc/passwd for read, create an output file in cwd for append,
cut the fields 1,3-4,6 from /etc/passwd and redirect that output to
the output file password, then close the two file handles for the
input and output files.

Here is the code:

#!/usr/bin/perl -w

use strict;
use warnings;

If you haven't done so already, please read the posting guidelines posted
here regularly.
my $FIN;
my $FOUT;
open ($FIN, "</etc/passwd") or die "Cannot open input file.\n";
open ($FOUT, ">>password") or die "Cannot open output file.\n";

I recommend using the 3 argument form of open. You also don't need to
declare $FIN and $FOUT separately. Finally, it is useful to report the
actual reason open failed:

open my $FIN, '<', '/etc/passwd'
or die "Cannot open '/etc/passwd': $!";

open my $FOUT, '>>', 'password'
or die "Cannot open 'password': $!";
while ($myline = <$FIN>) {

while(my $myline = <$FIN>) {

OK, so you have read a line from $FIN.
readline($FIN);

Now, you read another line and discard it.
$myline=$printable;

But this is the best. You now replace the contents of the line you had
earlier managed to read and store in $myline with the contents of
$printable. However, $printable is undef at this point. If you had used
strict, you would have caught this error.
print($FOUT,$printable,"\n");

Now that you have nuked $myline you attempt to output $printable to $FOUT.
You might want to check

perldoc -f print

because this will never output aything to $FOUT.
i $myline = chop($myline = `cut -d: -f1,3-4,6`);

Ahem, what is that 'i' up there. Oh, I see, you did not actually post the
code you ran on your system. Don't do that.

So, now you are over-writing the line you had stored in $myline with the
return value of the chop call. Do you know what chop returns? I have a
feeling you don't. You can look it up:

perldoc -f chop

[root@localhost james]# ./program.pl
Use of uninitialized value in print at ./program.pl line 12, <$FIN>
line 2.
GLOB(0x804ca88)

perl has just told you everything I said above.
[root@localhost james]#

Are you sure you want to mess with your system's crucial files while you
are logged in as root?
Thank you for your help.

You are welcome.

Sinan.

Hi Sinan,

Thanks again for the response, as embarrassing as it may have been to
me. But I apparently seem to be a glutton for punishment. After some
cleanup (the i was supposed to be a #) and reso (according to your
suggestions), here is the code, errors (new this time requiring
packages) and whatnot:

[root@localhost james]# ./program.pl
Global symbol "$printable" requires explicit package name at
../program.pl line 1
1.
Global symbol "$printable" requires explicit package name at
../program.pl line 1
2.
Execution of ./program.pl aborted due to compilation errors.
[root@localhost james]# cat program.pl
#!/usr/bin/perl -w
use strict;
use warnings;
#
open my $FIN, '<', '/etc/passwd'
or die "Cannot open '/etc/passwd': $!";
open my $FOUT, '>>', 'password'
or die "Cannot open 'password': $!";
#
while (my $myline = <$FIN>) {
$printable = chop ($myline = `cut -d: -f1,3-4,6`);
print($FOUT, $printable, "\n");
}
#
close ($FIN);
close ($FOUT);
#
[root@localhost james]#


Thanks again --

James
 
A

A. Sinan Unur

(e-mail address removed) (delfuego) wrote in

[ snipped previous exchange for brevity ]
Hi Sinan,

Thanks again for the response, as embarrassing as it may have been to
me. But I apparently seem to be a glutton for punishment.

I don't think of this as punishment.
After some cleanup (the i was supposed to be a #)

Yeah, you have too many of those '#' symbols all over the place. If there
is a good reason to do that, fine, but I find them distracting.
and reso (according to your suggestions),
reso?

here is the code, errors (new this time requiring packages)
and whatnot:

No, it is not requiring packages. See below.
[root@localhost james]# ./program.pl
Global symbol "$printable" requires explicit package name at
./program.pl line 1
1.
Global symbol "$printable" requires explicit package name at
./program.pl line 1
2.
Execution of ./program.pl aborted due to compilation errors.

Really, don't mess with your system files while you are logged in as root.
[root@localhost james]# cat program.pl
#!/usr/bin/perl -w

No need for -w now that you are using warnings.
use strict;
use warnings;
open my $FIN, '<', '/etc/passwd'
or die "Cannot open '/etc/passwd': $!";
open my $FOUT, '>>', 'password'
or die "Cannot open 'password': $!";
while (my $myline = <$FIN>) {
$printable = chop ($myline = `cut -d: -f1,3-4,6`);

You haven't checked the return value of chop, yet, have you? It is not what
you think it is:

perldoc -f chop

$printable is not declared anywhere and you are running under strict. You
need to declare your variables before using them under strict (so that
variables don't magically come to life when you misspell the name of a real
variable).

The declaration is normally made at the point the variable is first used,
that is:

my $printable = chop ($myline = `cut -d: -f1,3-4,6`);

But I don't think you really want to do that (hint: look up what chop
returns).
print($FOUT, $printable, "\n");
}

As I mentioned, you need to also look up the syntax for print:

perldoc -f print
close ($FIN);
close ($FOUT);

As for

($myline = `cut -d: -f1,3-4,6`);

I don't know what you think that line is doing.

See also Tad's response.

Sinan.
 
D

delfuego

Tad McClellan said:
delfuego said:
I am trying to write a simple Perl program to do the following:
Open /etc/passwd for read, create an output file in cwd for append,
cut the fields 1,3-4,6 from /etc/passwd and redirect that output to
the output file password, then close the two file handles for the
input and output files.


Here is a complete Perl program that does that:

perl -lne 'print join ":", (split /:/)[0,2,3,5]' /etc/passwd >>password

[root@localhost james]# ./program.pl


Yikes!

You shouldn't do things as root unless the thing *requires* that
you be root.

You do not need to be root to do what you describe above, so don't
be root when you are doing the above.

Thanks guys for the answers .. yes, reso was supposed to be redo, and
I did back up the system file before working on this program. I will
look up the perl docs for the commands I was trying to use as well,
not that I was trying to incurr your wrath(s), but it was frustrating
that I know I could do the same intent in just a bash script, in
Pascal or C as well .. but it was an exercise simple enough in theory
-- declare/open file handles, set the mode and declare the actual
files for I/O; loop while next line in file is not null, read a line
and format the output, write that output; and close the files.
Anyway, I will try your suggestions guys, thanks again.
*grin*
That grin was just that this is supposed to be an exercise for me to
learn basic file handling of Perl .. I have bigger and better projects
I want to work on that will require this basic knowledge.

Thanks -- James
 
D

delfuego

Tad McClellan said:
delfuego said:
I am trying to write a simple Perl program to do the following:
Open /etc/passwd for read, create an output file in cwd for append,
cut the fields 1,3-4,6 from /etc/passwd and redirect that output to
the output file password, then close the two file handles for the
input and output files.


Here is a complete Perl program that does that:

perl -lne 'print join ":", (split /:/)[0,2,3,5]' /etc/passwd >>password

[root@localhost james]# ./program.pl


Yikes!

You shouldn't do things as root unless the thing *requires* that
you be root.

You do not need to be root to do what you describe above, so don't
be root when you are doing the above.

Tad -- thanks! It worked.
I still need to learn a lot more Perl and scour your brain as well as
Sinan's in the futuer for answers probably.
Thanks again -- James
 
A

A. Sinan Unur

(e-mail address removed) (delfuego) wrote in
Tad McClellan said:
delfuego said:
I am trying to write a simple Perl program to do the following:
Open /etc/passwd for read, create an output file in cwd for append,
cut the fields 1,3-4,6 from /etc/passwd and redirect that output to
the output file password, then close the two file handles for the
input and output files.


Here is a complete Perl program that does that:

perl -lne 'print join ":", (split /:/)[0,2,3,5]' /etc/passwd
Tad -- thanks! It worked.
I still need to learn a lot more Perl and scour your brain as well as
Sinan's in the futuer for answers probably.

To get more information about command line options, type

perl -h

For detailed information, consult perldoc perlrun.

Sinan.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,161
Messages
2,570,892
Members
47,430
Latest member
7dog123

Latest Threads

Top