How can I read piped input in Perl on Windows?

2020-05-20 07:08发布

问题:

I am trying to create something in Perl that is basically like the Unix tee command. I'm trying to read each line of STDIN, run a substitution on it, and print it. (And eventually, also print it to a file.) This works if I'm using console input, but if I try to pipe input to the command it doesn't do anything. Here's a simple example:

print "about to loop\n";
while(<STDIN>)
{
  s/2010/2009/;
  print;
}
print "done!\n";

I try to pipe the dir command to it like this:

C:\perltest>dir | mytee.pl
about to loop
done!

Why is it not seeing the piped input? (I'm using Perl 5.10.0 on WinXP, if that is relevant.)

回答1:

This is actually a bug in how Windows handles IO redirection. I am looking for the reference right now, but it is that bug that requires you to specify

dir | perl filter.pl

rather than being able to use

dir | filter

See Microsoft KB article STDIN/STDOUT Redirection May Not Work If Started from a File Association:

  1. Start Registry Editor.
  2. Locate and then click the following key in the registry: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
  3. On the Edit menu, click Add Value, and then add the following registry value:
    • Value name: InheritConsoleHandles
    • Data type: REG_DWORD
    • Radix: Decimal
    • Value data: 1
  4. Quit Registry Editor.
C:\Temp> cat filter.pl
#!/usr/bin/perl

while ( <> ) {
    print "piped: $_";
}
C:\Temp> dir | filter
piped:  Volume in drive C is MAIN
piped:  Volume Serial Number is XXXX-XXXX
piped:
piped:  Directory of C:\Temp>
piped:
piped: 2010/03/19  03:48 PM              .
piped: 2010/03/19  03:48 PM              ..
piped: 2010/03/19  03:33 PM                32 m.pm
piped: 2010/03/19  03:48 PM                62 filter.pl


回答2:

Try:

C:\perltest>dir | perl mytee.pl


回答3:

Could it be Microsoft KB #321788?

Scripts that contain standard input (STDIN) and standard output (STDOUT) may not work correctly if you start the program from a command prompt and you use a file association to start the script.



回答4:

There's nothing wrong with trying to learn by doing, but a quick search of CPAN shows a number of possible solutions for the tee in Perl problem.

For example: PerlIO::Tee.



回答5:

Well IMHO, perl is poor substitute for sed ;)

dir | sed s/2009/2010/