在递归系统 bash 调用的参数内使用单引号
Using single quotes inside argument to recursive system bash call
我有一个 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
到 运行 命令时,三个备选方案中的 none 工作正常。
如何使用包含单引号的参数 运行 progB.pl
并同时使用 using bash -c
?
经过反复试验,我得出了:
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 在这个答案中建议的方法:
你应该首先避免这种疯狂的引用,但如果你坚持,你应该通过使用 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 );
我有一个 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
到 运行 命令时,三个备选方案中的 none 工作正常。
如何使用包含单引号的参数 运行 progB.pl
并同时使用 using bash -c
?
经过反复试验,我得出了:
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 在这个答案中建议的方法:
你应该首先避免这种疯狂的引用,但如果你坚持,你应该通过使用 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 );