首页 > 解决方案 > Windows cmd.exe 命令传递 Perl 系统函数在某些情况下需要双引号吗?

问题描述

Windows cmd.exe 命令 'type \Test\hello.txt' 必须用双引号引起来,以便 Perl system() 函数正确执行它。我没有在https://perldoc.perl.org/functions/systemhttps://perldoc.perl.org/perlport#system中找到此文档 - Windows 上的双引号要求是否记录在任何地方?

以下示例代码演示了perl \my\perl\perlsystest在版本 2004(OS Build 19041.867)的 Windows 10 Pro 服务器上的 Windows 命令提示符窗口中使用命令运行时出现的问题,Perl 级别为 v5.26.3


$cmd='type \Test\hello.txt' ;   # Set Windows DOS command to be executed
system('ECHO '.$cmd) ;          # Display command to be executed
system($cmd) == 0               # Execute command - note "\Test\hello.txt not found" error but with $? == 0
  or die "system(\"$cmd\") failed: $?!" ;
if ($? == -1) {print "system(\"$cmd\") failed to execute: $!!\n"}
elsif ($? & 127) {printf "system(\"$cmd\") child died with signal %d, %s coredump\n",
  ($? & 127),  ($? & 128) ? 'with' : 'without' ; exit}
elsif ($? != 0) {printf "system(\"$cmd\") child exited with value %d\n", $? ; exit}

$cmd='"'.$cmd.'"' ;             # Surround command string in double quotes
system('ECHO '.$cmd) ;          # Display command to be executed
system($cmd) == 0               # Execute command - note that command succeeds
  or die "system(\"$cmd\") failed: $?!" ;
if ($? == -1) {print "system(\"$cmd\") failed to execute: $!!\n"}
elsif ($? & 127) {printf "system(\"$cmd\") child died with signal %d, %s coredump\n",
  ($? & 127),  ($? & 128) ? 'with' : 'without' ; exit}
elsif ($? != 0) {printf "system(\"$cmd\") child exited with value %d\n", $? ; exit}

$cmd='type \Test\10hello.txt' ; # Set Windows DOS command to be executed
system('ECHO '.$cmd) ;          # Display command to be executed -  note that "type \Teshello.txt" is echoed
system($cmd) == 0               # Execute command - note "\Test\hello.txt not found" error but with $? == 0
  or die "system(\"$cmd\") failed: $?!" ;
if ($? == -1) {print "system(\"$cmd\") failed to execute: $!!\n"}
elsif ($? & 127) {printf "system(\"$cmd\") child died with signal %d, %s coredump\n",
  ($? & 127),  ($? & 128) ? 'with' : 'without' ; exit}
elsif ($? != 0) {printf "system(\"$cmd\") child exited with value %d\n", $? ; exit}

system('"ECHO '.$cmd).'"' ;     # Display command to be executed (with ECHO command in double quotes)
$cmd='"'.$cmd.'"' ;             # Surround command string in double quotes
system($cmd) == 0               # Execute command
  or die "system(\"$cmd\") failed: $?!" ;
if ($? == -1) {print "system(\"$cmd\") failed to execute: $!!\n"}
elsif ($? & 127) {printf "system(\"$cmd\") child died with signal %d, %s coredump\n",
  ($? & 127),  ($? & 128) ? 'with' : 'without' ; exit}
elsif ($? != 0) {printf "system(\"$cmd\") child exited with value %d\n", $? ; exit}

标签: windowsperlcmd

解决方案


你给系统的任何东西都必须适合处理命令的东西。对原始问题的评论应该变成答案。

system文档指向exec,它还说:

当参数通过系统外壳执行时,结果受制于其怪癖和功能。有关详细信息,请参见STRINGperlop 中的“”。

这也指向perlop中用于反引号的条目:

如何评估该字符串完全取决于系统上的命令解释器。在大多数平台上,如果您希望按字面意思处理 shell 元字符,则必须保护它们。这在实践中很难做到,因为不清楚如何转义哪些字符。

Perl 在这里没有解决单个系统,因为它支持的系统太多了(即使所有使用这些系统的人都消失了)。


你在那里贴了一堵文字墙,我不得不重写它来看看你在做什么。而不是重复相同的代码,一个子程序(具有一些合理的格式)对读者来说是礼貌的:)

my @commands = (
    'type \Test\hello.txt',
    q("type \Test\hello.txt")
    'type \Test\10hello.txt',
    );

foreach my $command ( @commands ) {
    try_it( $command );
    }

sub try_it  {
    my( $cmd ) = @_;
    system('ECHO '.$cmd); 
    system($cmd) == 0               # Execute command
      or die qq(system("$cmd") failed: $?!) ;
    if ($? == -1) {
        print qq(system("$cmd") failed to execute: $!!\n);
        }
    elsif ($? & 127) {
        printf qq(system("$cmd") child died with signal %d, %s coredump\n),
            ($? & 127),  ($? & 128) ? 'with' : 'without' ; 
        }
    elsif ($? != 0) {
        printf qq(system("$cmd") child exited with value %d\n), $? ; 
        }
    }

推荐阅读