0
votes

I have a while loop that should read lines either from STDIN or from file.

However, I'm not sure if this is possible to include if statements in the while loop to make it read lines from either STDIN or file.

Is there a way to manipulate on which lines while loop is operating (e.g. where lines are coming from)?

For example, I have set some keywords to know where the input is coming from based on what line arguments are provided and opened file to read lines.

I understand that one of the ways to solve this issue may be put STDIN into array first. The solution should not user arrays.

if ($argCount == 1) {
    $keyword = "input";
}
else {
    $keyword = "file";
    open ($out, '<', "temp.txt") or die "Cannot open file";
}

while ( ($line = <STDIN> && &keyword eq "input") || ($line = <$out> && $keyword eq "file") ) {
    print "$line\n";
    # do something with lines
}
     

In the above example, if STDIN, then it its printing only first line and does not move further; if file, then its just waiting for input on STDIN. I'm sure this is not the right way.

Expected output would be print out all lines from either STDIN or file. If keyword was set to "input", then $line = <STDIN> and prints all lines from STDIN. If keyword was set to "file, then $line = <$out> and prints all lines from the file.

1
I think you just want the "diamond operator": while(<>) { ... } reads from file(s) mentioned on the command line, or stdin if no files are provided. - Jim Garrison
@JimGarrison while (<>) reads starting from $ARGV[0], but what if the first argument is not a file? - J Szum
You can change @ARGV to be whatever you need at any point before invoking the diamond operator, so: shift @argv; before the while. - Jim Garrison
Re "what if the first argument is not a file?", Use something like Getopt::Long. It will remove from @ARGV the options it parses, leaving the just file(s). - ikegami

1 Answers

2
votes
my $fh;
if (...) {
   $fh = \*STDIN;
} else {
   open($fh, '<', ...)
      or die(...);
}

while (<$fh>) {
   ...
}

That said, you should simply be using

while (<>) {
   ...
}

If a file name is provided on the command line, the name file will be used. If not, STDIN will be used.