[Wylug-help] quotes within quotes within bash
Smylers
Smylers at stripey.com
Sat Nov 22 17:08:38 UTC 2008
Craig Hopkins writes:
> MYARGS="-a --delete -e \"/usr/bin/ssh -p1234\" "
So that's a single string, with some spaces and quotes in it.
> Why is it that when I do
>
> echo $MYARGS
That's splitting $MYARGS on spaces, and passing each chunk to echo as a
separate argument. echo then spits out each argument in turn --
separating them with spaces (thereby making it impossible for you to
distinguish those from the spaces that were in $MYARGS).
You can see what's happening by using something which shows what each of
its separate arguments are; here's a short Perl program which does that:
#! /usr/bin/perl
use Data::Dumper qw<Dumper>;
print Dumper @ARGV;
Save that in your path as args, make it executable, and you can do:
$ args $MYARGS
which emits:
$VAR1 = '-a';
$VAR2 = '--delete';
$VAR3 = '-e';
$VAR4 = '"/usr/bin/ssh';
$VAR5 = '-p1234"';
Note that arguments 4 and 5 are separate, and have the quote marks as
part of them.
For comparision, here's the desired output, which you get when passing
those arguments directly on the command line:
$ args -a --delete -e "/usr/bin/ssh -p1234"
$VAR1 = '-a';
$VAR2 = '--delete';
$VAR3 = '-e';
$VAR4 = '/usr/bin/ssh -p1234';
Note the shell interprets the quote marks, and never passes them to the
program.
So you need for $MYARGS to be interpreted by the shell like it does with
typed input -- splitting on spaces but keep quoted phrases together and
removing the quotes from what gets passed on. Bash has a bult-in eval
command which does just that:
$ eval args $MYARGS
$VAR1 = '-a';
$VAR2 = '--delete';
$VAR3 = '-e';
$VAR4 = '/usr/bin/ssh -p1234';
Bingo!
But there are various reasons why you might not want to use eval,
especially if any of the contents of $MYARGS is coming from external
sources.
What you actually have is a list of separate arguments you wish to store
in a variable. So rather than collapsing them to a string which later
has to be reparsed, instead store them in an array, one element per
argument:
$ MYARGS=(-a --delete -e "/usr/bin/ssh -p1234")
$ args "${MYARGS[@]}"
$VAR1 = '-a';
$VAR2 = '--delete';
$VAR3 = '-e';
$VAR4 = '/usr/bin/ssh -p1234';
Note that ${MYARGS[@]} needs quotes around it, to prevent your carefully
preserved arguments from being split on spaces anyway. That's just like
after doing:
$ drink='Curiosity Cola'
you still need the quotes in:
$ args "$drink"
$VAR1 = 'Curiosity Cola';
to prevent it becoming:
$ args $drink
$VAR1 = 'Curiosity';
$VAR2 = 'Cola';
Smylers
More information about the Wylug-help
mailing list