将带引号的字符串传递给system(),保持引号不变

Bor*_*din 9 quotes perl exec

此问题适用于Windows 10上的Perl v5.24.0

除了最简单的情况.在程序之间传递命令行和参数列表总是一个问题.考虑到空白和shell元字符的影响,可能使数据在几个级别的调用中保持不变,可能涉及到一堆逃逸和引号

灵丹妙药一直使用多参数形式system(也试图避免将shell作为中介调用),以便每个参数可靠地分离而不需要求助于引号

像这样的电话

system("dir \"C:\\Program Files\\\"")
Run Code Online (Sandbox Code Playgroud)

在这样写的眼睛上容易得多

system('dir', 'C:\Program Files\\')
Run Code Online (Sandbox Code Playgroud)

不过,我看不出有任何的方式来传递值是包括封闭报价

如果我写一个测试程序

show.pl

use Data::Dump;
dd \@ARGV;
Run Code Online (Sandbox Code Playgroud)

然后打电话

system('show', 'xxx')
Run Code Online (Sandbox Code Playgroud)

然后我得到的输出就是我的期望

["xxx"]
Run Code Online (Sandbox Code Playgroud)

但是,假设我想传递字符串"xxx".如果我试试

system('show', '"xxx"')
Run Code Online (Sandbox Code Playgroud)

然后引号在沿途的某个点被剥离,输出与前面的例子相同

如何调用system输出["\"xxx\""]

我已经尝试了各种逃避方法,但解决方案避开了我

ike*_*ami 4

问题:

system($^X, '-E', 'say @ARGV', '"test"');
Run Code Online (Sandbox Code Playgroud)

输出:

test
Run Code Online (Sandbox Code Playgroud)

那就太破了![1]


解决方案:

use Win32::ShellQuote qw( quote_system );

system(quote_system($^X, '-E', 'say @ARGV', '"test"'));
Run Code Online (Sandbox Code Playgroud)

输出:

"test"
Run Code Online (Sandbox Code Playgroud)
  1. 即使不使用 shell,Perl 也需要构建命令行。与 unix 不同,在 unix 中,执行程序的系统调用采用程序路径和参数列表,而 Windows执行程序的系统调用采用命令行,因此即使避免使用 shell,也必须构建命令行。Perl 似乎错误地构建了命令行。[2]这就是为什么使用system BLOCK LIST语法没有帮助的原因。

  2. 事实上,由应用程序解析命令行中的参数!值得庆幸的是,有一个系统调用可以做到这一点,因此标准已经形成。