Reputation: 21
I am trying to learn how to read from a process using filehandles. I have tried to write a program that opens a filehandle from the 'date' command and reference that as requested using the following program:
#!/usr/bin/perl
use warnings;
use diagnostics;
use strict;
open DATE, 'date|' or die "Cannot pipe from date: $!";
my $now;
while (1) {
print "Press any key: ";
chomp( my $result=<STDIN> );
$now = <DATE>;
print "\$now is: $now\n";
}
This works once, or initially, but subsequent 'loops' through the while (1), on the second time around I get an error about 'uninitialized value for $now'. Even stranger, the error goes away after the second loop, but the data from 'date' is never populated into the $now variable.
I presume this may indicate that the filehandle is being closed after the first run through, but I don't know if that is the case or not. I am just now learning perl, I'm sure this is easy and that I just don't have enough experience with the language.
Can anyone provide guidance for me on this? Should I not expect for the DATE filehandle to remain open after the initial run through the loop?
Here is the output from the program at this point:
$ perl ./test.perl
Press any key:
$now is: Fri Aug 17 15:00:27 EDT 2012
Press any key:
Use of uninitialized value $now in concatenation (.) or string at ./test.perl
line 16, <DATE> line 1 (#1)
(W uninitialized) An undefined value was used as if it were already
defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
To suppress this warning assign a defined value to your variables.
To help you figure out what was undefined, perl will try to tell you the
name of the variable (if any) that was undefined. In some cases it cannot
do this, so it also tells you what operation you used the undefined value
in. Note, however, that perl optimizes your program and the operation
displayed in the warning may not necessarily appear literally in your
program. For example, "that $foo" is usually optimized into "that "
. $foo, and the warning will refer to the concatenation (.) operator,
even though there is no . in your program.
$now is:
Press any key:
$now is:
Press any key:
$now is:
Press any key:
$now is:
Press any key: ^C
Upvotes: 2
Views: 542
Reputation: 107080
Your program is working as stated. The date command is returning a single line, and you're attempting to read pass the end of file.
The correct way would be:
#! /usr/bin/env perl
use warnings;
use diagnostics;
use strict;
use autodie;
use feature qw(say);
open my $date, "|-", "date";
while (my $now = <$date>) {
print "Press any key: ";
chomp( my $result=<STDIN> );
say "\$now is: $now";
}
And the program will execute a single loop.
A few things:
use feature qw(say);
allows you to use the say
command which is like print
except you don't have to keep putting \n
at the end.use autodie;
automatically allows open
statements to die without having to test them. If you're going to die from an open
anyway, why not let Perl do it for you.open
command is preferable. And, also to use scalars for file handles.What you probably want is something like this:
#! /usr/bin/env perl
use warnings;
use diagnostics;
use strict;
use autodie;
use feature qw(say);
for(;;) {
print "Press Return to continue...";
<STDIN>;
chomp ( my $date = qx(date) );
say qq(\$date = "$date");
}
qx(...)
means quote execute which is preferred over the back quotes.qq(...)
is another way to double quote strings. This allows you to use quotation marks without quoting them with backslashes.Upvotes: 0
Reputation: 98108
You are correct, date
only produces a single output and once you read it there is nothing left in the buffer. You can do something like this:
while (1) {
# ...
open DATE, 'date|' or die "Cannot pipe from date: $!";
$now = <DATE>;
close DATE;
# ...
print "\$now is: $now\n";
}
Another way is to use back tics:
while (1) {
print "Press any key: ";
chomp( my $result=<STDIN> );
print "now is: ".`date`."\n";
}
Upvotes: 4