【问题标题】:Using single quotes inside argument to recursive system bash call在递归系统bash调用的参数中使用单引号
【发布时间】:2015-03-20 08:27:39
【问题描述】:

我有一个 Perl 脚本 progA.pl,它需要使用 system 命令运行另一个 Perl 脚本 progB.pl。但是,progB.pl 已在 ~/.bashrc 中使用别名,因此我需要确保它在 ~/.bashrc 加载后运行。我可以通过使用bash-lc 选项来实现这一点。

对于这个问题,我尽可能简化问题,考虑以下版本的progB.pl

use feature qw(say);
use strict;
use warnings;
use Data::Dump qw(dd dump);

say "Received \@ARGV: " . dump @ARGV;

这里是progA.pl:

use feature qw(say);
use strict;
use warnings;

use Data::Dump qw(dd dump);

my $cmd = qq(progB.pl --opt='This option contains '"'"'single'"'"' quotes');
say "cmd = " . dump($cmd);
system( "$cmd" );
say "-----";
system( 'bash -c ' . "$cmd" );
say "-----";
system( 'bash -c ' . "'$cmd'" );
say "-----";
system( "bash -c  \"$cmd\"" );

跑步

$ progA.pl

给出输出:

cmd = "progB.pl --opt='This option contains '\"'\"'single'\"'\"' quotes'"   
Received @ARGV: "--opt=This option contains 'single' quotes"  
-----   
Received @ARGV: ()  
-----   
Received @ARGV: "--opt=This"  
-----   
Received @ARGV: "--opt=This option contains single quotes"

progB.pl 直接运行而不使用bash -c 时,我们看到这工作正常。当我使用bash -c 运行命令时,三个选项都没有正常工作。

如何使用包含单引号的参数运行progB.pl,同时使用bash -c

【问题讨论】:

  • 创建 perl 的原因之一是对多个递归 bash 调用以及您正在经历的引用地狱的反应。如果可以选择,我建议将 bash 脚本重写为 perl 模块...
  • @DovGrobgeld 好建议,但我认为这不是这种情况的选择..

标签: perl shell quoting


【解决方案1】:

您应该首先避免这种疯狂的引用,但如果您坚持,您应该使用system ARRAY 版本来避免至少一个级别的引用。

my $cmd = q{progB.pl --opt='This option contains '"'"'single'"'"' quotes'};
system( qw(bash -c), $cmd );

这使得它只是一个级别的疯狂引用。

my $option = q{This option contains 'single' quotes} =~ s/'/'"'"'/gr; # '
my $cmd = qq{progB.pl --opt='$option'};
system( qw(bash -c), $cmd );

在那里你可以做一些简单的助手

sub sq ($) { "'" . $_[0] =~ s/'/'"'"'/gr . "'" } # "

my $option = q{This option contains 'single' quotes};
my $cmd = qq{progB.pl --opt=@{[sq $option]}};
system( qw(bash -c), $cmd );

【讨论】:

  • 很好..所以对于每一级嵌套(相对于 bash),您可以添加一个新的调用 squ 子例程.. 它应该提供所需的正确引用量.. .
  • 是的,但是您应该首先尝试删除尽可能多的内容。
【解决方案2】:

经过反复试验,我得出了:

use feature qw(say);
use strict;
use warnings;

my $cmd = qq(print_first_arg.pl --opt='This option contains '"'"'single'"'"' quotes');
$cmd =~ s/'/'"'"'/g;
system( 'bash -c ' . "'$cmd'" );

这似乎有效,至少对于这个测试用例..

这也遵循@ysth 在此答案中建议的方法: https://stackoverflow.com/a/24869016/2173773

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-31
    • 2012-07-19
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    • 2010-10-04
    • 2011-08-11
    相关资源
    最近更新 更多