我如何逃避一个任意的string作为Windows中的命令行参数?

我有一个string列表,我想在一个Windows命令行调用中将这些string作为parameter passing。 对于简单的字母数字string,只需逐字传递:

> script.pl foo bar baz yes no foo bar baz yes no 

我明白,如果一个参数包含空格或双引号,我需要反斜杠 – 转义双引号和反斜杠,然后双引号。

 > script.pl foo bar baz "\"yes\"\\\"no\"" foo bar baz "yes"\"no" 

但是,当我尝试通过字面百分号的参数时,发生这种情况:

 > script.pl %PATH% C:\Program Files\PHP\;C:\spaceless\perl\bin\;C:\Program Files\IBM\Java60\bin; (...etc.) 

双引号不起作用:

 > script.pl "%PATH%" C:\Program Files\PHP\;C:\spaceless\perl\bin\;C:\Program Files\IBM\Java60\bin; (...etc.) 

也不反斜杠(注意输出中反斜杠是如何存在的):

 > script.pl \%PATH\% \%PATH\% 

而且,对于反斜杠转义的反斜线,这些规则是不一致的:

 > script.pl "\\yes\\" \\yes\ > script.pl "\yes\\" \yes\ > script.pl "\yes\" \yes" 

而且,毫无疑问,Windows命令行shell中有特殊字符,就像在所有shell中一样。 那么,什么是安全地转义在Windows命令行中使用的任意命令行参数的一般过程呢?

理想的答案将描述一个函数escape() ,它可以用在像下面这样的情况下(一个Perl例子):

 $cmd = join " ", map { escape($_); } @args; 

下面是一些应该安全地通过这个函数逃脱的示例string(我知道其中的一些看起来类Unix,这是故意的):

 yes no child.exe argument 1 Hello, world Hello"world \some\path with\spaces C:\Program Files\ she said, "you had me at hello" argument"2 \some\directory with\spaces\ " \ \\ \\\ \\\\ \\\\\ "\ "\T "\\T !1 !A "!\/'" "Jeff's!" $PATH %PATH% & <>|&^ ()%!^"<>&| >\\.\nul malicious argument"&whoami *@$$A$@#?-_ 

Solutions Collecting From Web of "我如何逃避一个任意的string作为Windows中的命令行参数?"

这是一个MSDN博客帖子,展示了如何。 然而,它假设每一个命令行程序在内部使用CommandLineToArgvW来解析它的命令行(不是一个简单的假设,因为它是Shell32库的一部分)。

http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx

要转义命令行参数 ,请使用以下命令:

 sub escapeArg { my $arg = shift; # Sequence of backslashes followed by a double quote: # double up all the backslashes and escape the double quote $arg =~ s/(\\*)"/$1$1\\"/g; # Sequence of backslashes followed by the end of the arg, # which will become a double quote later: # double up all the backslashes $arg =~ s/(\\*)$/$1$1/; # All other backslashes do not need modifying # Double-quote the whole thing $arg = "\"".$arg."\""; # Escape shell metacharacters $arg =~ s/([()%!^"<>&|;, ])/\^$1/g; return $arg; } 

为了逃避实际的命令行命令 ,例如当调用带有荒谬名称的命令()!&%PATH%^;, .exe例如()!&%PATH%^;, .exe (这是完全合法的)时,请使用以下命令:

 sub escapeCmd { my $arg = shift; # Escape shell metacharacters $arg =~ s/([()%!^"<>&|;, ])/\^$1/g; return $arg; } 

请注意,对命令使用escapeArg()将不起作用。

资料来源: