: '7th edition Bourne shell aka the V7 shell did not know # as comment sign, yet.'
: 'Workaround: the argument to the : null command can be considered a comment,'
: 'protect it, because the shell would have to parse it otherwise.'
####
sub shell_comment_quote {
return '' unless @_;
unless (@_ == 1) {
croak "Too many arguments to shell_comment_quote "
. "(got " . @_ . " expected 1)";
}
local $_ = shift;
s/\n/\n#/g;
return $_;
}
##
##
sub shell_quote {
my ($rerr, $s) = _shell_quote_backend @_;
if (@$rerr) {
my %seen;
@$rerr = grep { !$seen{$_}++ } @$rerr;
my $s = join '', map { "shell_quote(): $_\n" } @$rerr;
chomp $s;
croak $s;
}
return $s;
}
##
##
sub shell_quote_best_effort {
my ($rerr, $s) = _shell_quote_backend @_;
return $s;
}
##
##
sub _shell_quote_backend {
my @in = @_;
my @err = ();
# ...
return \@err, '' unless @in;
# ...
if (s/\x00//g) {
push @err, "No way to quote string containing null (\\000) bytes";
}
# ...
return \@err, $ret;
}
##
##
sub _shell_quote_backend {
my @in = @_;
my @err = ();
if (0) {
require RS::Handy;
print RS::Handy::data_dump(\@in);
}
return \@err, '' unless @in;
my $ret = '';
my $saw_non_equal = 0;
foreach (@in) {
if (!defined $_ or $_ eq '') {
$_ = "''";
next;
}
if (s/\x00//g) {
push @err, "No way to quote string containing null (\\000) bytes";
}
my $escape = 0;
# = needs quoting when it's the first element (or part of a
# series of such elements), as in command position it's a
# program-local environment setting
if (/=/) {
if (!$saw_non_equal) {
$escape = 1;
}
}
else {
$saw_non_equal = 1;
}
if (m|[^\w!%+,\-./:=@^]|) {
$escape = 1;
}
if ($escape
|| (!$saw_non_equal && /=/)) {
# ' -> '\''
s/'/'\\''/g;
# make multiple ' in a row look simpler
# '\'''\'''\'' -> '"'''"'
s|((?:'\\''){2,})|q{'"} . (q{'} x (length($1) / 4)) . q{"'}|ge;
$_ = "'$_'";
s/^''//;
s/''$//;
}
}
continue {
$ret .= "$_ ";
}
chop $ret;
return \@err, $ret;
}
##
##
>bash --version
GNU bash, version 4.3.48(1)-release (x86_64-slackware-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
>echo with some arguments !
with some arguments !
>foo with some arguments !
-bash: foo: command not found
>'!' foo
-bash: !: command not found
>! foo
-bash: foo: command not found
>
##
##
>bash --version
GNU bash, version 4.3.48(1)-release (x86_64-slackware-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
>perl -MString::ShellQuote=shell_quote -E 'say shell_quote("!","FOO=BAR","baz")'
! FOO=BAR baz
>! FOO=BAR baz
-bash: baz: command not found
>'!' FOO=BAR baz
-bash: !: command not found
>! 'FOO=BAR' baz
-bash: FOO=BAR: command not found
>