2011-10-29 37 views
7

我遇到了Windows命令解释器的一个非常奇怪的问题。它发生在XP和Windows 7上。我的下面的描述适用于Perl脚本,但是这个问题适用于在命令行上运行任何类型的程序,其中包含命令行参数。在Windows命令提示符中出现双引号副作用

对于我使用的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] 

如预期。特殊字符| <>在双引号内工作良好,但是当外引号用^来转义时。

然而,当一个双引号被添加到引用PARAM例如,在

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

然后我得到的错误 -

> was unexpected at this time. 

但是,如果双引号特殊字符后,来到| <或>,那么它工作正常。

你可以通过转义特殊| <>带引号的参数内的^字符。 如

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] 

即它对待管道|作为文字字符,并且不会出现管道。

有没有人有任何这个问题的经验,并知道任何解决方法?

我已经编写了一些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" 

作品,因为\”而来的特殊字符之后| 。

It必须是命令解释器中的错误。我想知道更多关于此的信息,并在可能的情况下找到解决方法。这个问题混淆了运行一些有用的脚本。对于一名命令解释者来说,这是一个非常明显的问题。我也尝试过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] 

因此证实了如预期此命令行会工作。这些脚本可以在命令行上使用任意数量的管道。


附加信息:

,我觉得我能得到这个使用多种解决方法的工作 - 例如^“哈利提到的一个例子有时你可以recraft正则表达式,以避免使用。”如果在特殊字符前有两个“序列”,则不会发生问题。在运行任何命令之前,我运行check-params.pl和check-pipe.pl来验证Perl脚本如何看到命令行参数,例如上面的OP编辑描述了这些脚本,这些脚本自从我的OP以来我已经修改过了。

+0

虽然我相信我找到了解决方案(请参阅我的答案的最新编辑),如果您以交互方式输入正则表达式,您可能会发现脚本更方便地提示它们,而不是将它们放在命令行。这样你就不必逃避所有的特殊字符。 –

+0

非常感谢您的信息。我从我的OP测试中获得了“转义序列”的印象,对我来说,通过提示输入命令行参数是不可行的,因为我有很多命令,而且它们非常复杂。他们从一个文本文件,有时我复制几个并一次运行它们(使用快速编辑模式,你可以右键单击粘贴到命令窗口) –

回答

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

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

+0

^“是相当有用的,我已经添加这对我的许多解决方法。这里似乎有两个问题,一个是Windows命令解释程序的工作方式,另一个是Perl如何解析命令行。 –

相关问题