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