【问题标题】:Escaped Double Quote Side Effect in Windows Command PromptWindows 命令提示符中的转义双引号副作用
【发布时间】:2011-12-17 21:16:22
【问题描述】:

我在使用 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 与 ^ 在带引号的参数内。 例如

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

然而,转义的双引号不仅会影响特殊字符 | 在 current 参数中,但它会影响任何后续参数中的这些特殊字符。

例如,如果我这样做 -

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 日志文件,其中一个使用了正则表达式,我在命令行的一个带引号的参数中传递了它。正则表达式可能包含诸如 | 之类的字符。 ,它也可能有一个双引号,我输入为\“。因此出现了上述问题。

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


感谢您的回复,但在 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]

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


其他信息:

我发现我可以使用多种变通方法来实现这一点 - 例如,Harry 提到的 ^" 就是一个例子。有时您可以重新制作正则表达式以避免使用 ".如果在特殊字符 | 之前有两个 \" 序列,则不会出现问题。在运行任何命令之前,我运行 check-params.pl 和 check-pipe.pl 以验证 Perl 脚本将如何查看命令行参数,例如,对我的 OP 的上述编辑描述了这些脚本,这些脚本是我自 OP 以来修改的。

【问题讨论】:

  • 尽管我相信我已经为您找到了解决方案(请参阅我的答案的最新编辑),如果您以交互方式输入正则表达式,您可能会发现脚本提示它们更方便而不是将它们放在命令行上。这样您就不必转义所有特殊字符。
  • 非常感谢您的信息。我从我的 OP 中的测试中得到的印象是 \" 是一个转义序列。通过提示输入命令行参数对我来说是不可行的,因为我有很多命令而且它们非常复杂。我复制并粘贴它们从一个文本文件中,有时我会复制几个并一次运行它们。(在快速编辑模式下,您只需右键单击以粘贴到命令窗口中)。

标签: windows escaping command-prompt


【解决方案1】:

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

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^"

产生所需的结果。这是通过转义所有特殊字符(包括引号)来实现的。

【讨论】:

  • The ^" 很有帮助,我已经将它添加到我的众多解决方法中。这里似乎有两个问题,一个是 Windows 命令解释器的工作原理,另一个是 Perl 如何解析命令行。
猜你喜欢
  • 1970-01-01
  • 2010-09-20
  • 1970-01-01
  • 2020-07-03
  • 2011-07-08
  • 1970-01-01
  • 1970-01-01
  • 2020-11-26
相关资源
最近更新 更多