首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用bash的Perl backticks

使用bash的Perl backticks
EN

Stack Overflow用户
提问于 2022-02-08 12:08:38
回答 6查看 230关注 0票数 2

在Perl中,执行backticks的默认shell是sh。我想切换到使用bash,因为它更丰富的语法。到目前为止,我发现建议的解决方案是

代码语言:javascript
复制
`bash -c \"echo a b\"`

明显的缺点是转义双引号,这意味着我将有困难使用双引号在我的bash。例如,如果我想在bash中运行需要双引号的命令

代码语言:javascript
复制
echo "a'b"

上面的方法会很尴尬。

Perl的system()调用有一个解决方案:要使用数组args,

代码语言:javascript
复制
system("bash", "-c", qq(echo "a'b"));

这使我原来的bash命令保持不变,而且几乎总是如此。

我也想在后排使用数组args。有可能吗?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2022-02-08 19:12:19

捕捉:微小是一个非常好的选择:如概要所示,您可以这样做

代码语言:javascript
复制
use Capture::Tiny 'capture';
my ($output, $error_output, $exit_code) = capture {
    system(@whatever);
};

以及在capture_stdout内部使用系统,如果您想要更简单的回退行为。

另外,它是非常通用的,使用Perl代码(甚至是执行奇怪操作的Perl代码)以及外部程序,所以在工具箱中使用它是件好事。

票数 2
EN

Stack Overflow用户

发布于 2022-02-08 18:07:29

首先,可以向qx提交一个列表;它被内插到一个字符串中,然后传递给execvp或shell (参见qx,以及这个职位和注释的第二部分)。如果您需要一个shell,那么该字符串可能包含shell元字符,因此它通过shell进行。

代码语言:javascript
复制
my @cmd = qw(ls -l "dir with spaces");
#my @cmd = qw(ls -l "dir with spaces" > outfile);
my @out = qx(@cmd);
print for @out;

我创建了一个"dir with spaces"目录,其中包含一个文件以进行测试。(对于带有引号的命令,可以使用shell。)

接下来,我原则上建议使用一个模块来编写这些shell命令,而不是通过咬钉子器来正确地转义和传递它,比如弦乐:ShellQuote

代码语言:javascript
复制
use String::ShellQuote qw(shell_quote); 

my @cmd = ('ls', '-l', q(dir with spaces)); 

my $quoted = shell_quote(@cmd);; 
my @out = qx($quoted); 
#my @out = qx($quoted > outfile); 
print for @out;

我使用单引号的q(...)运算符形式来演示另一种方法(对于包含单引号也很有用);对于这个简单的示例来说,这是不必要的。人们仍然需要谨慎对待细节;这是使用复杂的外部命令的本质,任何方法或工具都无法完全避免。

至于运行bash,请注意,通常情况下,sh委托给系统上的默认排序shell,而在许多系统上使用的是bash。但是,如果它不在您的命令中,那么在命令中使用bash -c的一种方法是首先准备命令,然后将其添加到qx字符串中

代码语言:javascript
复制
my @cmd = ('ls', '-l', q(dir with spaces)); 
my $quoted = shell_quote(@cmd); 
my @out = qx(bash -c "$quoted"); 
#my @out = qx(bash -c "$quoted" > outfile); 
print for @out;

我还想给你几张纸条:

  • qx是一个古老的恶魔。使用现代工具/模块运行外部命令如何?为了准备所涉及的bash字符串,可能还有更多的工作要做,但是其他的事情都会更好。有很多选择。例如
代码语言:javascript
复制
- [IPC::System::Simple](https://metacpan.org/pod/IPC::System::Simple) with its few utility functions
代码语言:javascript
复制
- Use [Capture::Tiny](https://metacpan.org/pod/Capture::Tiny) to wrap a `system` call with syntax you prefer
代码语言:javascript
复制
- The [IPC::Run](https://metacpan.org/pod/IPC::Run) can do any and all of this and then way way more
  • 为什么要使用外部命令,而Perl(远)更丰富呢?它是一个完整的、非常完整的编程语言,与具有一些编程功能的命令解释器相比。如果您需要shell的功能,为什么不通过shell运行这些功能,并在Perl中执行其他所有操作呢?
票数 4
EN

Stack Overflow用户

发布于 2022-02-08 15:42:20

我有下面的潜艇可以工作

代码语言:javascript
复制
    sub bash_output {
       my ($cmd) = @_; 
    
       open my $ifh, "-|", "bash", "-c", $cmd or die "cannot open file handler: $!";
    
       my $output = ""; 
       while (<$ifh>) {
          $output .= $_; 
       }   
    
       close $ifh;
    
       return $output;
    }

    print "test bash_output()\n";

    my @strings = (
         qq(echo "a'b"),
         'echo $BASH_VERSION',
         '[[ "abcde" =~ bcd ]] && echo matched',
         'i=1; ((i++)); echo $i',
   );

   for my $s (@strings) {
         print "bash_output($s) = ", bash_output($s), "\n";
   }

输出是

代码语言:javascript
复制
bash_output(echo "a'b") = a'b

bash_output(echo $BASH_VERSION) = 4.4.20(1)-release

bash_output([[ "abcde" =~ bcd ]] && echo matched) = matched

bash_output(i=1; ((i++)); echo $i) = 2

我的回答是冗长的,但它满足了我的需要。我本来希望Perl有一个内置的解决方案,就像它如何处理system()调用一样,我仍然希望。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71033653

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档