我正在尝试在 perl 中使用以下命令,但它给了我错误
system("zcat myfile.gz | wc > abc.txt");
但是当我运行它时,我在意外标记 `|' 附近收到错误语法错误
即使我删除>abc.txt
我仍然收到错误。
我们可以将管道与系统命令一起使用吗?
以下是错误详情:
sh: -c: line 1: syntax error near unexpected token `|'
sh: -c: line 1: ` | wc '
下一次,测试您的演示程序以确保它确实表现出您所说的行为。你实际上跑了一些更接近的东西
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");
}
它按预期工作:
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 ,这样效率更高。
尝试使用反引号执行包含cut -d \|
命令的管道时收到此错误消息。原来我不得不双重转义管道字符,例如cut -d \\|