Ros*_*son 7 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";
}
Run Code Online (Sandbox Code Playgroud)
因此,如果我跑 -
perl check-params.pl "a b|<>" c^|^<^>cc
Run Code Online (Sandbox Code Playgroud)
然后输出是
[Param: a b|<>]
[Param: c|<>cc]
Run Code Online (Sandbox Code Playgroud)
正如所料.特殊的字符| <>在双引号内工作正常,但在外部引号时,你用^来转义它们.
但是,当引用的参数添加双引号时,例如
perl check-params.pl "a\" b|<>"
Run Code Online (Sandbox Code Playgroud)
然后我得到错误 -
> was unexpected at this time.
Run Code Online (Sandbox Code Playgroud)
但如果双引号出现在特殊字符|之后 <或>,然后它工作正常.
你可以通过转义特殊的|来轻松解决这个问题 <> char,带引号参数内的^.例如
perl check-params.pl "a\" b^|"
Run Code Online (Sandbox Code Playgroud)
但是,转义的双引号不仅影响特殊字符| 当前参数中的<> 但它会影响任何后续参数中的这些特殊字符.
例如,如果我这样做 -
perl check-params.pl "aa \"bb" ccc | perl check-pipe.pl
Run Code Online (Sandbox Code Playgroud)
(check-pipe.pl只需输出管道收到的东西 -
use strict;
use warnings;
while (<STDIN>) {
print "PIPE RECEIVED ---> $_";
}
Run Code Online (Sandbox Code Playgroud)
)
然后输出是 -
Param: [aa "bb]
Param: [ccc]
Param: [|]
Param: [perl]
Param: [check-pipe.pl]
Run Code Online (Sandbox Code Playgroud)
即它对待管道 作为文字字符,没有管道发生.
有没有人有这个问题的经验,知道任何解决方法?
我编写了一些用于处理Web日志文件的Perl脚本,并且使用了正则表达式,我在命令行上的一个引用的参数中传递.正则表达式可能包含诸如|之类的字符 <>,它也可能有一个双引号,我输入为"."因此上面的问题正在出现.
任何帮助非常感谢,谢谢.
感谢您的回复,但在XP SP3上尝试此操作时,Perl脚本会看到两个命令行参数.
这个问题与Perl无关,例如
echo "a \"b|c"
Run Code Online (Sandbox Code Playgroud)
产生错误 -
'c"' is not recognized as an internal or external command,
operable program or batch file.
Run Code Online (Sandbox Code Playgroud)
但
echo "a b|\"c"
Run Code Online (Sandbox Code Playgroud)
工作,因为\"来自特殊的char |.
它必须是命令解释器中的错误.我有兴趣了解更多相关信息,并在可能的情况下找到解决方法.这个问题困扰着运行一些有用的脚本.对于命令解释器来说,这是一个非常明显的问题.我也试过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";
}
Run Code Online (Sandbox Code Playgroud)
check-pipe.pl: -
use strict;
use warnings;
while (<STDIN>) {
print "PIPE RECEIVED: $_";
}
while (my $param = shift @ARGV) {
print "COMMAND LINE RECEIVED: [$param]\n";
}
Run Code Online (Sandbox Code Playgroud)
例如跑步: -
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
Run Code Online (Sandbox Code Playgroud)
产生输出: -
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]
Run Code Online (Sandbox Code Playgroud)
从而确认此命令行将按预期工作.这些脚本可以在命令行上使用任意数量的管道.
附加信息:
我发现我可以使用多种解决方法来实现这一点 - 例如^"Harry提到的是一个例子.有时你可以重新制作正则表达式以避免使用".当在特殊char | <>之前有两个"序列"时,问题就不会发生.在运行任何命令之前,我运行check-params.pl和check-pipe.pl来验证Perl脚本将如何看到命令行参数,例如上面对我的OP的编辑描述了这些脚本,我从OP开始修改了这些脚本.
\" 中的双引号被认为与初始双引号匹配,结束带引号的参数。要在带引号的参数中包含双引号,请使用两个双引号:
perl check-params.pl "a"" b|<>"
Run Code Online (Sandbox Code Playgroud)
应该会产生您期望的结果,具体取决于 perl.exe 如何解析命令行参数(我已经使用命令脚本进行了测试,因为我没有安装 Perl)。您需要更改脚本,以便将“”而不是\”视为双引号。
附加:此命令行
echo "a \"b|c"
Run Code Online (Sandbox Code Playgroud)
导致错误消息启动c" is not recognized。 这不是一个错误。
反斜杠不是转义字符,因此命令行包含一个带引号的字符串 ( "a \"),后跟一个管道 ( |),这使得其余 ( c") 成为附加命令,echo 命令的输出通过管道传输到其中。
如果你说
echo "a ""b|c"
Run Code Online (Sandbox Code Playgroud)
那么只有一个带引号的字符串 ( "a ""b|c") ,它将按预期工作。
不幸的是,我现在可以确认 ActivePerl 的命令行解析会导致
perl check-params.pl "a"" b|"
Run Code Online (Sandbox Code Playgroud)
分成两个参数。您可能需要获取整个命令行(如果有办法在 Perl 中做到这一点)并自己解析它。
额外的:
perl check-params.pl ^"a\^" b^|c^"
Run Code Online (Sandbox Code Playgroud)
产生所需的结果。这是通过转义所有特殊字符(包括引号)来实现的。