1

我想运行这里看到的这个命令

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

从perl,我试过system

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

但它导致:

sh: 1: Syntax error: "(" unexpected

有谁知道诀​​窍吗?

此外,当从两个可能需要转义的变量中读取string1和读取时,如何安全地运行这种命令?string2

4

3 回答 3

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);
于 2012-12-27T14:26:32.743 回答
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);
于 2012-12-27T14:14:15.107 回答
0

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

#!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 打印到屏幕上,而是捕获输出并自己打印——因为我认为您可能想要对输出做一些事情而不仅仅是查看它。

新版本(无/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;
}

string1并且string2可以是任何东西,包括来自父进程的变量或其他命令的输出。

于 2012-12-27T15:35:24.590 回答