Activestate: how to read from a file or default to STDIN

H

Henry Law

(Googled a lot for this without success; a good search string eluded
me).

I have a Perl program running under ActiveState Perl which needs to
read in a number of control statements before it gets to work. I want
to be able to specify the name of the file containing the control
statements (myprog.pl -f filename), but have it default to STDIN if no
name is supplied (myprog.pl). I can't find a neat way of coding it.

This works (aside from an ActiveState problem I'll come to):

#! C:\Perl\bin\Perl.exe
use strict;
use warnings;

use Getopt::Std;
our $opt_f;
getopts('f:');
my @control_commands;

if (defined $opt_f) {
open (COMMANDS,$opt_f) or
die "Couldn't open command file '$opt_f'$!";
@control_commands = <COMMANDS>;
} else {
print "Enter control commands, Ctrl-D to finish:";
@control_commands = <STDIN>; # See problem described later
}

print for (@control_commands);
__END__

But it requires me to slurp the whole control file in at one go; there
won't ever be more than a dozen or so statements so it'll work OK, but
it's inelegant. What I'd like to do is (lapsing into pseudocode here
and there as I really can't work out how to code this ...)

if (defined $opt_f) {
open ($file_handle,$opt_f) or
die "Couldn't open command file '$opt_f'$!";
} else {
open ($file_handle,STDIN); # doesn't compile
}

while (my $command = <$file_handle> ) {
do_stuff_with_single_command;
}

.... there must be a "usual" way of doing this; could someone point me
in the right direction?

In passing, I can't find the ActiveState equivalent of Ctrl-D to
terminate STDIN - and it's not in the html manual as far as I can see.
Can someone help with that?
 
A

Anno Siegel

Henry Law said:
(Googled a lot for this without success; a good search string eluded
me).

I have a Perl program running under ActiveState Perl which needs to
read in a number of control statements before it gets to work. I want
to be able to specify the name of the file containing the control
statements (myprog.pl -f filename), but have it default to STDIN if no
name is supplied (myprog.pl). I can't find a neat way of coding it.

This works (aside from an ActiveState problem I'll come to):

#! C:\Perl\bin\Perl.exe
use strict;
use warnings;

use Getopt::Std;
our $opt_f;
getopts('f:');
my @control_commands;

if (defined $opt_f) {
open (COMMANDS,$opt_f) or
die "Couldn't open command file '$opt_f'$!";
@control_commands = <COMMANDS>;
} else {
print "Enter control commands, Ctrl-D to finish:";
@control_commands = <STDIN>; # See problem described later
}

print for (@control_commands);
__END__

But it requires me to slurp the whole control file in at one go; there
won't ever be more than a dozen or so statements so it'll work OK, but
it's inelegant. What I'd like to do is (lapsing into pseudocode here
and there as I really can't work out how to code this ...)

if (defined $opt_f) {
open ($file_handle,$opt_f) or
die "Couldn't open command file '$opt_f'$!";
} else {
open ($file_handle,STDIN); # doesn't compile
}

while (my $command = <$file_handle> ) {
do_stuff_with_single_command;
}

... there must be a "usual" way of doing this; could someone point me
in the right direction?

You would use a "lexical filehandle". In the case of a specified
file, you get it through open. If you need STDIN, you can assign
a globref to STDIN, which works as a filehandle through magic.

use Getopt::Std;
getopts( 'f:', \ my %opt); # I prefer a single lexical hash

my $fh;
if (defined $opt{ f}) {
open ( $fh, $opt{ f}) or
die "Couldn't open command file '$opt{ f}'$!";
} else {
print "Enter control commands, Ctrl-D to finish:";
$fh = \ *STDIN;
}
my @control_commands = <$fh>; # could be done line-wise now
__END__

Anno
 
H

Henry Law

You would use a "lexical filehandle". In the case of a specified
file, you get it through open. If you need STDIN, you can assign
a globref to STDIN, which works as a filehandle through magic.

Aha ... magic is the bit I need to learn more of!
my $fh;
if (defined $opt{ f}) {
open ( $fh, $opt{ f}) or
die "Couldn't open command file '$opt{ f}'$!";
} else {
print "Enter control commands, Ctrl-D to finish:";
$fh = \ *STDIN;

....etc. Thank you.

And of course as soon as I'd posted I found a way of googling for the
right way to terminate STDIN on Windows - Ctrl-Z, followed by Enter.
 
T

Tad McClellan

Henry Law said:
In passing, I can't find the ActiveState equivalent of Ctrl-D to
terminate STDIN -


That is because it has nothing to do with ActiveState Perl, managing
STDIN is the Operating System's job.

The answer is in the docs for Windows (I expect), not for Perl.

and it's not in the html manual as far as I can see.
Can someone help with that?


Ctrl-Z marks the end of input in Windows terminals.
 

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

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top