Как я могу избежать произвольной строки для использования в качестве аргумента командной строки в Windows? - PullRequest
6 голосов
/ 21 июня 2011

У меня есть список строк, и я хочу передать эти строки в качестве аргументов в одном вызове командной строки 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 есть специальные символы, как во всех оболочках. Какова общая процедура безопасного экранирования произвольных аргументов командной строки для использования в командной строке 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$@#?-_

Ответы [ 2 ]

4 голосов
/ 12 июля 2011

Для экранирования командной строки аргумент используйте следующее:

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() для команды не будет работать.

Источники:

4 голосов
/ 26 июня 2011

Вот пост блога 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/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...