【问题标题】:Why doesn't a * in my pipe open in Perl work on Windows?为什么我在 Perl 中打开的管道中的 * 不能在 Windows 上运行?
【发布时间】:2010-11-09 20:22:14
【问题描述】:

我在使用 Perl 时遇到了这个奇怪的问题。我正在尝试从我的 Perl 脚本中执行一个外部程序,这个外部程序将字符串 + 通配符作为参数。我的 Perl 程序是这样的

my $cmd_to_run = 'find-something-in-somedb myname* |' 
open(procHandle, $cmd_to_run); # I am using open because I want to 
                               # parse the output using pipes

由于某些奇怪的原因,运行这个 Perl 脚本(在 Windows 下)调用 open 函数最终会出错:

'sqlselect' is not recognized as an internal or external command

我猜它与我的命令字符串中的* 有关,因此我将其删除,现在我的命令字符串看起来像这样

my $cmd_to_run = 'find-something-in-somedb myname|'

现在,当我运行我的 Perl 脚本时,它工作得非常好。只有存在通配符时才会出现问题。

需要注意的几点:

  1. 我在同一个 cmd 提示符(我正在执行这个 perl 脚本的地方)中运行了带有通配符字符的相同命令,它运行得非常好..

  2. 当我在 C 中使用 Windows 中的 _open 函数对其进行编程时,相同的命令可以工作。

  3. 问题似乎只存在于通配符 * 存在时,至少这是我的猜测

  4. 不,我没有在 Unix 中尝试过这个..

有什么线索???

EDIT :我发现这与 ENV 有关。我尝试运行的程序仅在搜索字符串中存在“*”通配符时才使用“sqlselect”... find-something-in-somedb 和 sqlselect 都存在于同一位置。在这种情况下,perl 如何找到“find-in-db”而不是“sqlselect”

对不起,我意识到原来的问题现在变成了其他问题。与“ENV”有关,而不是通配符 *

【问题讨论】:

    标签: windows perl environment-variables pipe wildcard


    【解决方案1】:

    建议使用open的三元形式

    open(procHandle, '-|', 'find-something-in-somedb', 'myname*');
    

    因为它绕过了外壳(它将执行* 扩展)。

    但是,在 Windows 上,应用程序通常会执行自己的引号解析和 * 扩展,因此您可能需要

    open(procHandle, '-|', 'find-something-in-somedb', '"myname*"');
    

    甚至

    open(procHandle, '-|', 'find-something-in-somedb "myname*"');
    

    因为我不确定 Perl 究竟是如何以及何时将事情交给cmd

    【讨论】:

    • 我猜这与 $PATH 有关。当它们都存在于同一个网络目录中时,Perl 能够找到“find-in-db”而不是“sqlselect”。并且这个网络目录被添加到我的 cmd 提示会话中的路径变量中。
    • 发现这是一个愚蠢的区分大小写的问题。该死的我不能再傻了。问题是 sqlselect 存在于同一目录中,但它的文件名是“SqlSelect”,而 perl 似乎不喜欢这样。
    • 这很奇怪,因为在 Windows 上,查找名为“sqlselect”的文件应该匹配名为“SqlSelect”的文件...但一切都很好如果你设法解决了这个问题。我仍然建议改用 3-arg open:一般来说这是一个好习惯。
    【解决方案2】:

    Perl 很可能会扩展通配符本身,而您不想这样做。 ephemient提供的答案很好,但是为了调试这个,试着调用这个非常简单的程序:

    print join ' ', @ARGV;
    

    将其放入自己的文件中,然后从您的原始程序中调用它(我将其命名为 argv.pl):

    my $cmd_to_run = './argv.pl myname* |' 
    open(procHandle, $cmd_to_run); 
    

    这将在您的平台上明确地告诉您 Perl 是如何解析事物的。在 Unix 上,* 被扩展以匹配当前工作目录中的文件。虽然不确定Windows。

    【讨论】:

      【解决方案3】:

      如果你使用三参数open会发生什么?

      open my $procHandle, '-|', 'find-something-in-somedb myname*'
          or die "Cannot open pipe: $!";
      

      【讨论】:

      • 我会投赞成票以平衡它,但确实......投反对票并且没有评论解释原因?
      • @ephemient 非常感谢。我理解我的回答是否被忽略,因为它是你的一个子集,但我有点惊讶地看到它被积极地否决了(就像我想我应该删除它一样 ;-) @James Thompson 我认为我们同意这是常见的礼貌至少告诉试图帮助的人他做错了什么。谢谢。
      猜你喜欢
      • 2023-03-05
      • 2010-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-10
      • 1970-01-01
      • 2012-09-07
      相关资源
      最近更新 更多