2

I want to read from the default input if data is piped in or a file is provided, but if nothing is given I would like to supply a default for while(<>) to execute on.

Pseudocode:

if(!<>){
  <> = system("ls | ./example.pl");
}

while(<>){
...
...
...
}
Chris
  • 11,819
  • 19
  • 91
  • 145
  • What part of your implementation is tripping you up? – Dan Fego Jan 27 '12 at 01:26
  • This doesn't seem to be valid. I want to set <>. Also the test (`if(!<>)`) doesn't seem correct. – Chris Jan 27 '12 at 01:27
  • @Chris right, none of that is really sensible. `<>` is an operator that reads from a file. You can't set it, and doing `if(!<>)` reads a line from somewhere and tests whether *that line* is true or false. – hobbs Jan 27 '12 at 01:32
  • @hobbs hence the "Pseudocode" prompt. I know that is incorrect and am asking how to do the equivalent – Chris Jan 27 '12 at 03:39

2 Answers2

5

Your "if data is piped in" makes things difficult. It's easy to say

if (!@ARGV) {
    @ARGV = ("somedefault");
}

while (<>) {
    ...
}

which will operate on "somedefault" if no filenames are given on the commandline — but that means you'll never get the Perl default of reading from stdin if there aren't any filenames on the commandline.

One possible compromise is to use the -t operator to guess whether stdin is a terminal:

if (!@ARGV && -t STDIN) {
    @ARGV = ("somedefault");
}

Which will use "somedefault" if there are no filenames on the commandline and stdin is attached to a terminal, but it will use stdin if there are no filenames and stdin is redirected from a file or a pipe. This is a little magical (maybe annoyingly so), but does what you asked for.

hobbs
  • 223,387
  • 19
  • 210
  • 288
  • When I try that, substituting `(some default)` with `system("ls")` the terminal runs forever. Am I piping it in wrong? I also tried "ls | ./ctime" but that seems infinitely recursive. – Chris Jan 27 '12 at 03:37
  • 1
    Neither of those makes sense. `"ls|"` might make sense. – hobbs Jan 27 '12 at 03:56
4

How about trying to read from <>, and then falling back to your default if nothing was read?

while (my $line = <>)
{
     do_stuff($line);
}

# if no lines were read, fall back to default data source
if (not $.)
{
     while (my $line = <SOMETHING_ELSE>)
     {
          do_stuff($line);
     }
}

You can read about the $. variable here, at perldoc perlop - it indicates the "current" line number of the most recent filehandle read from. If it is undefined, there was nothing to read from <>.

Ether
  • 53,118
  • 13
  • 86
  • 159