Экранированный побочный эффект двойной кавычки в командной строке Windows

я столкнулся с очень странной проблемой с помощью интерпретатора команд Windows. Это происходит как на XP, так и на Windows 7. Мое описание ниже относится к скрипту Perl, но эта проблема относится к запуску любой программы в командной строке, которая принимает параметры командной строки.

Для теста я использую Perl-скрипт check-params.pl который просто выводит то, что он видел как параметры -

use strict;
use warnings;
while (my $param = shift @ARGV) {
    print "Param: [$param]n";
}

таким образом, если я сбегу -

perl check-params.pl "a b|<>" c^|^<^>cc

тогда выход

[Param: a b|<>]
[Param: c|<>cc]

как и ожидалось. Специальные символы | отлично работают внутри двойных кавычек, но когда внешние кавычки вы избегаете их с ^.

однако, когда двойная цитата добавляется к цитируемому параметру, например, в

perl check-params.pl "a" b|<>"

тогда я получаю ошибку -

> was unexpected at this time.

но если двойная цитата после специальный символ / , Затем он работает нормально.

вы можете легко исправить это, избегая специального / char с ^ внутри указанного параметра. например!--19-->

perl check-params.pl "a" b^|"

однако не только экранированная двойная кавычка влияет на специальные символы | в настоящее параметр, но он влияет на эти специальные символы внутри любых последующих параметров.

например, если я сделаю это -

perl check-params.pl "aa "bb" ccc | perl check-pipe.pl

(где check-pipe.pl просто выводит то, что трубы получены -

use strict;
use warnings;
while (<STDIN>) {
    print "PIPE RECEIVED ---> $_";
}

)

тогда выход -

Param: [aa "bb]
Param: [ccc]
Param: [|]
Param: [perl]
Param: [check-pipe.pl]

ie он обрабатывает трубу | как буквальный символ, и никакой трубопровод не происходит.

есть ли у кого-нибудь опыт этой проблемы и знаете ли о каком-либо обходном пути ?

я написал несколько сценариев Perl для обработки файлов веб-журналов, и один использует regex, которые я передаю внутри цитируемого параметра в командной строке. Регулярное выражение может содержать символы, такие как|, и оно также может иметь двойную кавычку, которую я ввожу как ". Таким образом, возникает вышеупомянутая проблема.

любая помощь очень ценится, спасибо.


Спасибо за ответ, но при попытке этого на XP SP3, Perl скрипт видит два параметра командной строки.

эта проблема не связана с Perl, например

echo "a "b|c"

выдает ошибку -

'c"' is not recognized as an internal or external command,
operable program or batch file.

но

echo "a b|"c"

работает, потому что " приходит после специального символа |.

это должно быть ошибка в интерпретаторе команд. Мне было бы интересно узнать больше об этом и найти обходной путь, если вероятный. Эта проблема мешает запуску некоторых полезных скриптов. Это довольно вопиющая проблема для интерпретатора команд. Я также попробовал Windows 7, и та же проблема возникает там с вышеупомянутым тестом echo.


Дополнительная Информация:

я обновил скрипты check-params.pl и check-pipe.pl чтобы дать больше полезной информации : -

check-params.pl :-

use strict;
use warnings;
while (my $param = shift @ARGV) {
    print "COMMAND LINE RECEIVED: [$param]n";
}

check-pipe.pl :-

use strict;
use warnings;
while (<STDIN>) {
    print "PIPE RECEIVED: $_";
}

while (my $param = shift @ARGV) {
    print "COMMAND LINE RECEIVED: [$param]n";
}

например бег :-

perl pl/utils/check-params.pl l1 l1-b l1-c | perl pl/utils/check-pipe.pl l2 l2-b | perl pl/utils/check-pipe.pl l3 l3-b | perl pl/utils/check-pipe.pl united arsenal rangers raith

производит выход :-

PIPE RECEIVED: PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l1]
PIPE RECEIVED: PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l1-b]
PIPE RECEIVED: PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l1-c]
PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l2]
PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l2-b]
PIPE RECEIVED: COMMAND LINE RECEIVED: [l3]
PIPE RECEIVED: COMMAND LINE RECEIVED: [l3-b]
COMMAND LINE RECEIVED: [united]
COMMAND LINE RECEIVED: [arsenal]
COMMAND LINE RECEIVED: [rangers]
COMMAND LINE RECEIVED: [raith]

таким образом, подтверждая, что эта командная строка будет работать, как ожидалось. Скрипты будут работать с любым количеством каналов в командной строке.


Дополнительная Информация:

я нахожу, что могу заставить это работать, используя многочисленные обходные пути-например, ^ " Гарри упомянул один пример. Иногда вы можете recraft регулярное выражение, чтобы избегайте использования ". Когда есть две " последовательности перед специальным символом/, проблема не возникает. Перед запуском любого commmand я запускаю check-params.pl и check-pipe.pl чтобы проверить, как скрипты Perl будут видеть параметры командной строки, например, выше edit to my OP описывает эти скрипты, которые я изменил с момента моего OP.

1 ответов


двойная кавычка в \ " считается соответствующей начальной двойной кавычке, заканчивающейся параметром quoted. Чтобы включить двойную кавычку в параметр quoted, используйте две двойные кавычки:

perl check-params.pl "a"" b|<>"

должен дать результат, который вы ожидаете, в зависимости от того, как perl.exe анализирует параметры командной строки (я тестировал с помощью командных скриптов, поскольку у меня не установлен Perl). Вам нужно будет изменить свой скрипт так, чтобы "" вместо \ " рассматривался как двойной цитата.

дополнительные: эта командная строка

echo "a \"b|c"

приводит к появлению сообщения об ошибке c" is not recognized. это не ошибка.

обратная косая черта не является escape-символом, поэтому командная строка содержит одну строку с кавычками ("a \") вслед за трубой (|) что делает отдых (c") дополнительная команда, в которую передается вывод команды echo.

если вы вместо этого скажи

echo "a ""b|c"

тогда есть только одна строка с кавычками ("a ""b|c") и он будет работать, как ожидалось.

к сожалению, теперь я могу подтвердить, что синтаксический анализ командной строки ActivePerl вызывает

perl check-params.pl "a"" b|"

разбить на два параметра. Вам может потребоваться получить всю командную строку (если есть способ сделать это в Perl) и проанализировать ее самостоятельно.

дополнительные:

perl check-params.pl ^"a\^" b^|c^"

дает желаемый результат. Эта работа избегая всех специальных символов, включая кавычки.