在嵌套的单引号,反引号和引用内逃脱美元符号

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.

amo*_*mon 6

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)