【问题标题】:How can I read piped input in Perl on Windows?如何在 Windows 上读取 Perl 中的管道输入?
【发布时间】:2011-01-29 14:52:40
【问题描述】:

我正在尝试在 Perl 中创建一些基本上类似于 Unix tee 命令的东西。我正在尝试读取STDIN 的每一行,对其进行替换,然后打印出来。 (最终,也将其打印到文件中。)如果我使用控制台输入,这可以工作,但如果我尝试将输入通过管道传递给命令,它不会做任何事情。这是一个简单的例子:

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

我尝试像这样通过管道将 dir 命令传递给它:

C:\perltest>目录| mytee.pl 即将循环 完毕!

为什么看不到管道输入? (如果相关的话,我在 WinXP 上使用 Perl 5.10.0。)

【问题讨论】:

标签: windows perl pipe stdin


【解决方案1】:

这实际上是 Windows 处理 IO 重定向的一个错误。我现在正在寻找参考资料,但正是那个错误需要您指定

dir | perl filter.pl

而不是能够使用

dir | filter

请参阅 Microsoft 知识库文章 STDIN/STDOUT Redirection May Not Work If Started from a File Association

  1. 启动注册表编辑器。
  2. 在注册表中找到并单击以下项: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
  3. 在编辑菜单上,单击添加值,然后添加以下注册表值:
    • 值名称:InheritConsoleHandles
    • 数据类型:REG_DWORD
    • 基数:Decimal
    • 数值数据:1
  4. 退出注册表编辑器。
C:\Temp> cat filter.pl
#!/usr/bin/perl

而(){
    打印“管道:$_”;
}
C:\Temp> 目录 |筛选
管道:驱动器 C 中的卷是 MAIN
管道:卷序列号为 XXXX-XXXX
管道:
管道:C:\Temp> 目录
管道:
管道:2010 年 3 月 19 日下午 3 点 48 分。
管道:2010/03/19 03:48 PM ..
管道:2010/03/19 03:33 PM 32 m.pm
管道:2010/03/19 03:48 PM 62 filter.pl

【讨论】:

  • 感谢思南,非常有用的答案。这使得我不需要 icky 批处理文件解决方法
  • @Jenni 当然,缺点是您无法确定 InheritConsoleHandles 是否已设置在您可能部署脚本的任何其他计算机上(这是 pl2bat.bat 出现的地方)。感谢您接受我的回答。
  • 我发现这个 Windows 错误无法可靠地重现。我第一次必须使用 dir | perl 过滤器.pl。但第二次,它只适用于 dir |过滤器.pl。讨厌。
【解决方案2】:

试试:

C:\perltest>dir | perl mytee.pl

【讨论】:

  • hmm...这行得通,但为什么我必须这样指定呢?
  • 因为你在windows上。在 unix 上,您可以将 #!/usr/bin/perl 放在 perl 文件的顶部,以告诉 shell perl 所在的位置。在 windows 上只能直接执行 .exe 和 .com 文件。
  • 好的,在我的例子中,“c:\scripts”在 %PATH% 中,而“.PL”在 %PATHEXT% 中。我希望能够从任何地方拨打foo | mytee,而不必记住在这种情况下我需要在它前面放一个“perl”,最后放一个“.pl”。有什么建议还是我不走运?
  • @Jenni 您可以使用pl2bat 将您的 Perl 脚本转换为批处理文件,然后 Windows 将很乐意通过管道传输。
  • 好吧,我找到了解决方法。我在 c:\scripts 中创建了一个“mytee.bat”文件。该bat文件的第一行有@echo off,第二行有perl c:\scripts\mytee.pl %1 %2。这行得通——输入通过 bat 文件传送到 perl 脚本。由于 .bat 在我的 PATHEXT 中的 .pl 之前,因此“mytee”执行“mytee.bat”而不是 perl 脚本。
【解决方案3】:

会不会是Microsoft KB #321788

包含标准输入的脚本 (STDIN) 和标准输出 (STDOUT) 如果您开始可能无法正常工作 命令提示符下的程序和 您使用文件关联开始 脚本。

【讨论】:

  • 听起来这就是问题所在。我找到了一种解决方法,涉及通过 bat 文件进行管道传输,然后调用 perl 可执行文件(请参阅接受的答案)。谢谢!
  • +1 @zoul 我正忙着查找信息,我没有注意到您已经发布了链接。
【解决方案4】:

尝试边做边学并没有错,但是快速搜索 CPAN 显示了许多可能的解决方案,可以解决 Perl 中的 tee 问题。

例如:PerlIO::Tee

【讨论】:

    【解决方案5】:

    恕我直言,perl 不能很好地替代 sed ;)

    dir | sed s/2009/2010/

    【讨论】:

    • 我简化了脚本中与我的问题无关的部分。
    • 但是 perl 是一个很好的替代品:'sed' is not recognized as an internal or external command, operable program or batch file ;-)
    猜你喜欢
    • 1970-01-01
    • 2012-06-01
    • 2015-10-28
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多