roo*_*099 2 bash perl dpkg perl5
我想使用Perl在文件的每一行上运行shell命令.该文件包含诸如的包名firefox.
这是对单个包名称的调用; 有用:
dpkg-query -W -f='${binary:Package}_${Version}' firefox
Run Code Online (Sandbox Code Playgroud)
如果我从这样的单行"文件"管道它不再起作用:
echo firefox | perl -ne \
'print `dpkg-query -W -f="${binary:Package}_${Version}" $_` . "\n"'
Run Code Online (Sandbox Code Playgroud)
输出是_\n.那么在这些嵌套引号中逃避这些美元的正确方法是什么,以便dpkg-query接收${binary:Package}_${Version}不带shell 的bba 或bash将它们解释为"他们的"变量的逐字字符串?我尝试了各种排列但到目前为止无济于事.输出应该是表格firefox_59.0.2+build1-0ubuntu0.16.04.1\n.
shell命令中的Perl脚本中的shell命令中有一个格式字符串.这种嵌套水平使得逃避非常困难,因此最好的解决方案是摆脱不必要的水平.
在这里,最简单的方法是摆脱内部shell命令.您不需要通过shell运行dpkg命令,并且可以直接执行它.这将避免在Perl中处理任何类型的shell元字符.例如:
perl -ne 'chomp; system q(dpkg-query), q(-W), q(-f=${binary:Package}_${Version}), $_; print qq(\n)'
Run Code Online (Sandbox Code Playgroud)
这将直接将命令输出打印到STDOUT,而不首先捕获它.与使用反引号一样,这不会进行任何错误处理.要获得真正的退出代码,您需要$? >> 8.因此,通过适当的错误处理,命令将如下所示:
perl -ne '
chomp;
@command = (q(dpkg-query), q(-W), q(-f=${binary:Package}_${Version}), $_);
system(@command) == 0 or die sprintf qq(Command [%s] exited with status %d\n), qq(@command), $? >> 8;
print qq(\n)'
Run Code Online (Sandbox Code Playgroud)