如何在perl中运行这种命令?

时间:2012-12-27 13:53:47

标签: perl bash

我想运行此命令,看到here

diff  <(echo "string1" ) <(echo "string2")

来自perl,我尝试了system

system('diff  <(echo "string1" ) <(echo "string2")');

但它导致:

sh: 1: Syntax error: "(" unexpected

有人知道这个伎俩吗?

此外,如果从可能需要转义的两个变量中读取string1string2,如何安全地运行此类命令?

3 个答案:

答案 0 :(得分:4)

使用bash执行命令

system('/bin/bash -c \'diff  <(echo "string1" ) <(echo "string2")\'');

默认情况下,系统将使用/ bin / sh执行命令,而/ bin / sh不支持功能'()'

对于安全运行,需要转义关键字符,例如。引用这里。

错误代码:

my $var1 = "\"string1;ls";
my $var2 = "\"string2;ls";
my $cmd = "diff <(echo \"$var1\") <(echo \"$var2\" )";
print $cmd . "\n";
my @args = ("bash", "-c", $cmd);
system(@args);
print "=======" . "\n";

安全代码:

$var1 = "\"string1;ls";
$var2 = "\"string2;ls";
$var1 =~ s/(\")/\\$1/g;
$var2 =~ s/(\")/\\$1/g;
$cmd = "diff <(echo \"$var1\") <(echo \"$var2\" )";
print $cmd . "\n";
@args = ("bash", "-c", $cmd);
system(@args);

答案 1 :(得分:1)

我正在修理这个,即使它没有处理空格(就像你想要的那样),它也不会引用第一个字符。我做得更聪明,所以它没有引用明显的东西。

# this will escape all the characters in the string  
my $str = '/?\abc"';
( my $str3 = $str) =~ s/([^a-zA-Z0-9])/\\\1/g;

printf ("%s\n",$str);
printf ("%s\n",$str3);

my @args = ( "bash", "-c", 'diff <(echo "$foo" ) <(echo "string2")' );

system(@args);

答案 2 :(得分:0)

无shell(但可能不太便携)版本:

#!perl
use strict;
use warnings;
use Fcntl;

open my $one, '-|', 'echo', 'string1' or die "$! opening first input";
fcntl $one, F_SETFD, (fcntl($one, F_GETFD, 0) & ~FD_CLOEXEC)
  or die "$! keeping open first input";
open my $two, '-|', 'echo', 'string2' or die "$! opening second input";
fcntl $two, F_SETFD, (fcntl($two, F_GETFD, 0) & ~FD_CLOEXEC)
  or die "$! keeping open second input";

open my $diff, '-|', 'diff', "/dev/fd/".fileno($one), "/dev/fd/".fileno($two)
  or die "$! running diff";

while (<$diff>) {
    print;
}

这基本上就是shell的作用(打开第一个“echo”命令的子进程,打开第二个“echo”命令的子进程,允许子进程继承其文件句柄,然后打开子进程到“diff”命令,其参数是指向打开的文件句柄的特殊文件名。唯一的区别是,我们不是让diff打印到屏幕上,而是捕获输出并自己打印 - 因为我认为你可能想要对输出做一些事情,而不仅仅是它。 / p>

新版本(没有/ bin / echo,没有转义,没有死锁)

#!/usr/bin/perl
use strict;
use warnings;
use Fcntl;

my $pid_one = open my $one, '-|';
die "$! opening first input" unless defined $pid_one;
if (!$pid_one) { # child
    print "string1\n";
    exit;
}
fcntl $one, F_SETFD, (fcntl($one, F_GETFD, 0) & ~FD_CLOEXEC)
  or die "$! keeping open first input";

my $pid_two = open my $two, '-|';
die "$! opening second input" unless defined $pid_two;
if (!$pid_two) { # child
    print "string2\n";
    exit;
}
fcntl $two, F_SETFD, (fcntl($one, F_GETFD, 0) & ~FD_CLOEXEC)
   or die "$! keeping open second input";

 open my $diff, '-|', 'diff', "/dev/fd/".fileno($one), "/dev/fd/".fileno($two)
  or die "$! running diff";
 while (<$diff>) {
    print;
}

string1string2可以是任何内容,包括来自父进程的变量或其他命令的输出。