如何在Windows中转义任意字符串以用作命令行参数?

问题描述 投票:6回答:2

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

> 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;

这里有一些更多的示例字符串应该由此函数安全地转义(我知道其中一些看起来像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$@#?-_
windows shell cmd
2个回答
4
投票

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

原始链接(可能不起作用):http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx

网站存档链接:https://web.archive.org/web/20190109172835/https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/


4
投票

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

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(完全合法)时),请使用以下命令:

sub escapeCmd {
  my $arg = shift;

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

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

资料来源:

© www.soinside.com 2019 - 2024. All rights reserved.