在Windows命令提示符中转义双引号副作用

时间:2011-10-29 14:54:08

标签: windows escaping command-prompt

我遇到了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]

正如所料。特殊的字符| &LT; &GT;在双引号内工作正常,但在外引号时,你用^。

来逃避它们

但是,当引用的参数添加双引号时,例如

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

然后我收到错误 -

> was unexpected at this time.

但是如果双引号来自之后的特殊字符| &LT;或者&gt;,然后就可以了。

您可以通过转义特殊的|来轻松解决此问题&LT; &GT;带引号参数的^内的char。 例如

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

然而,转义双引号不仅会影响特殊字符| &LT; &GT;在当前参数中,它会影响任何后续参数中的这些特殊字符。

例如,如果我这样做 -

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]

即它处理管道作为文字字符,没有管道发生。

有没有人遇到过这个问题,知道有什么解决方法吗?

我编写了一些Perl脚本来处理Web日志文件,其中一个使用正则表达式,我在命令行上的引用参数中传递。正则表达式可能包含诸如|之类的字符&LT; &gt;,它也可能有一个双引号,我输入为“。”因此上面的问题就出现了。

非常感谢任何帮助,谢谢。


感谢您的回复,但是在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上试过,上面的回声测试也出现了同样的问题。


其他信息:

我已更新脚本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]

从而确认此命令行将按预期工作。这些脚本可以在命令行上使用任意数量的管道。


其他信息:

我发现我可以使用多种解决方法来实现这一点 - 例如^“Harry提到的是一个例子。有时你可以重新制作正则表达式以避免使用”。当在特殊char |&lt;&gt;之前有两个\“序列时,问题就不会发生。在运行任何命令之前,我运行check-params.pl和check-pipe.pl来验证Perl脚本将如何看到命令行参数,例如上面对我的OP的编辑描述了这些脚本,我从OP开始修改了这些脚本。

1 个答案:

答案 0 :(得分:2)

\“中的双引号被认为与初始双引号匹配,结束了引用的参数。要在引用参数中包含双引号,请使用两个双引号:

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

应该产生您期望的结果,具体取决于perl.exe如何解析命令行参数(我已经使用命令脚本进行了测试,因为我没有安装Perl)。您需要更改脚本,以便将“”而不是“”视为双引号。

附加:此命令行

echo "a \"b|c"

会导致出现c" is not recognized的错误消息。 这不是错误。

反斜杠不是转义字符,因此命令行包含一个带引号的字符串("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^"

产生所需的结果。这可以通过转义所有特殊字符来起作用,包括引号。