如何在 Perl 的 system() 中使用 bash 语法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/571368/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 17:58:07  来源:igfitidea点击:

How can I use bash syntax in Perl's system()?

perlbashcommand

提问by Frank

How can I use bashsyntax in Perl's system()command?

如何bash在 Perl 的system()命令中使用语法?

I have a command that is bash-specific, e.g. the following, which uses bash's process substitution:

我有一个特定于 bash 的命令,例如以下命令,它使用 bash 的进程替换:

 diff <(ls -l) <(ls -al)

I would like to call it from Perl, using

我想从 Perl 调用它,使用

 system("diff <(ls -l) <(ls -al)")

but it gives me an error because it's using shinstead of bashto execute the command:

但它给了我一个错误,因为它使用sh而不是bash执行命令:

sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `sort <(ls)'

回答by vladr

Tell Perl to invoke bash directly. Use the listvariant of system()to reduce the complexity of your quoting:

告诉 Perl 直接调用 bash。使用 的list变体system()来降低引用的复杂性:

my @args = ( "bash", "-c", "diff <(ls -l) <(ls -al)" );
system(@args);

You may even define a subroutine if you plan on doing this often enough:

如果您计划经常这样做,您甚至可以定义一个子程序:

sub system_bash {
  my @args = ( "bash", "-c", shift );
  system(@args);
}

system_bash('echo $SHELL');
system_bash('diff <(ls -l) <(ls -al)');

回答by David Z

 system("bash -c 'diff <(ls -l) <(ls -al)'")

should do it, in theory. Bash's -coption allows you to pass a shell command to execute, according to the man page.

应该这样做,理论上。-c根据手册页,Bash 的选项允许您传递要执行的 shell 命令。

回答by errant.info

The problem with vladr's answers is that system won't capture the output to STDOUT from the command (which you would usually want), and it also doesn't allow executing more than one command (given the use of shift rather than accessing the full contents of @_).

vladr 的答案的问题在于系统不会从命令中捕获输出到 STDOUT(您通常需要),并且它也不允许执行多个命令(考虑到使用 shift 而不是访问完整的@_ 的内容)。

Something like the following might be more suited to the problem:

类似以下内容可能更适合该问题:

my @cmd = ( 'diff <(ls -l) <(ls -al)', 'grep fu' );
my @stdout = exec_cmd( @cmd );
print join( "\n", @stdout );

sub exec_cmd
{
    my $cmd_str = join( ' | ', @_ );
    my @result = qx( bash -c '$cmd_str' );
    die "Failed to exec $cmd_str: $!" unless( $? == 0 && @result );
    return @result;
}

Unfortunately this won't prevent you from invoking /bin/sh just to run bash, however I don't see a workaround for this issue.

不幸的是,这不会阻止您调用 /bin/sh 来运行 bash,但是我没有看到此问题的解决方法。

回答by some guy

I prefer to execute bash commands in perl with backticks "`". This way I get a return value, e.g.:

我更喜欢在 perl 中执行带有反引号“`”的 bash 命令。这样我得到一个返回值,例如:

my $value = \`ls`;

Also, I don't have to use "bash -c" just to run a commmand. Works for me.

另外,我不必使用“bash -c”来运行命令。对我来说有效。

回答by Shujun Ou

Inspired by the answer from @errant.info, I created something simpler and worked for me:

受到@errant.info 答案的启发,我创建了一些更简单的东西并对我来说有效:

my $line="blastn -subject <(echo -e \"$seq1\") -query <(echo -e \"$seq2\") -outfmt 6";
my $result=qx(bash -c '$line');
print "$result\n";

The introduced $line variable allows modifying inputs ($seq1 and $seq2) each time. Hope it helps!

引入的 $line 变量允许每次修改输入($seq1 和 $seq2)。希望能帮助到你!