2

我正在尝试在 perl 中使用以下命令,但它给了我错误

system("zcat myfile.gz | wc > abc.txt");

但是当我运行它时,我在意外标记 `|' 附近收到错误语法错误

即使我删除>abc.txt我仍然收到错误。

我们可以将管道与系统命令一起使用吗?

以下是错误详情:

sh: -c: line 1: syntax error near unexpected token `|'
sh: -c: line 1: ` | wc '
4

3 回答 3

5

下一次,测试您的演示程序以确保它确实表现出您所说的行为。你实际上跑了一些更接近的东西

while (my $file_name = <>) {
   system("zcat $file_name | wc > abc.txt");
}

其中有两个错误:

  • 您没有删除尾随换行符,因此 shell 试图执行

    zcat def.gz
     | wc >abc.txt
    

    代替

    zcat def.gz | wc >abc.txt
    
  • 在将文件名嵌入命令之前,您没有将文件名转换为 shell 文字。

    考虑如果文件名包含空格会发生什么。你会执行

    zcat def ghi.gz | wc >abc.txt
    

    代替

    zcat 'def ghi.gz' | wc >abc.txt
    

解决方案:

use String::ShellQuote qw( shell_quote );

while (my $file_name = <>) {
   chomp($file_name);
   system("zcat -- ".shell_quote($file_name)." | wc > abc.txt");
}
于 2013-02-01T13:05:08.483 回答
1

它按预期工作:

perl -lne 'system("cat *.java|wc");'

也许你的文件名有些奇怪。

你可以像这样检查你的shell的插值:

my @file = `ls -1 myfile*.gz`;chomp(@files);
print join("\n",@files);

在 perl 中还有其他可能执行的操作,例如反引号、用 | 打开、qx。

如果您对文件名有疑问,您可以自己获取文件名并以特定方式调用系统以避免执行shell:http ://docstore.mik.ua/orelly/perl/cookbook/ch19_07.htm

如果只有一个标量参数,则检查该参数是否有 shell 元字符,如果有,则将整个参数传递给系统的命令 shell 进行解析(在 Unix 平台上是 /bin/sh -c,但在其他平台)。如果参数中没有 shell 元字符,则将其拆分为单词并直接传递给 execvp ,这样效率更高。

于 2013-02-01T11:20:21.237 回答
0

尝试使用反引号执行包含cut -d \|命令的管道时收到此错误消息。原来我不得不双重转义管道字符,例如cut -d \\|

于 2018-10-19T13:17:33.343 回答