tags:

views:

1841

answers:

4

There is an example of "how to do this" on Stuart Colville's blog, but the example used there and the explanation of why it works is unclear.

To keep things simple:

Let's say you have a bash alias like

alias rxvt='urxvt'

which works fine.

alias rxvt='urxvt -fg '#111111' -bg '#111111''

won't work, and neither will:

alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''

So how do you end up matching up opening and closing quotes inside a string once you have escaped quotes?

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\'#111111'\''

seems ungainly although it would represent the same string if you're allowed to concatenate them like that.

+5  A: 

I don't see the entry on his blog (link pls?) but according to the gnu reference manual

Enclosing characters in single quotes (‘'’) preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.

so bash won't understand

alias x='y \'z '

however, you can do this if you surround with double quotes:

alias x="echo \'y "
> x
> 'y
Steve B.
http://muffinresearch.co.uk/archives/2007/01/30/bash-single-quotes-inside-of-single-quoted-strings/
cons
+7  A: 

And if you really want to use single quotes in the outermost layer, remember that you can glue both kinds of quotation. Example:

 alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
                       12345

Explanation:

(1) End first quotation which uses single quotes.

(2) Start second quotation, using double-quotes.

(3) Quoted character.

(4) End second quotation, using double-quotes.

(5) Start third quotation, using single quotes.

If you do not place whitespace between (1) and (2), or between (4) and (5), shell will interpret that as one long word.

liori
+1 for the One True Solution. Need I add that you should write code to do this kind of quoting?
Norman Ramsey
Wow. That's hard to keep straight even with a clear explanation!
Clinton Blackmore
+1  A: 

I'm not specifically addressing the quoting issue because, well, sometimes, it's just reasonable to consider an alternative approach.

rxvt() { urxvt -fg "#${1:-000000}" -bg "#${2:-FFFFFF}"; }

which you can then call as:

rxvt 123456 654321

the idea being that you can now alias this without concern for quotes:

alias rxvt='rxvt 123456 654321'

or, if you need to include the # in all calls for some reason:

rxvt() { urxvt -fg "${1:-#000000}" -bg "${2:-#FFFFFF}"; }

which you can then call as:

rxvt '#123456' '#654321'

then, of course, an alias is:

alias rxvt="rxvt '#123456' #654321'"

(oops, i guess i kind of did address the quoting :)

nicerobot
I was trying to put something within single quotes that was in double quotes which were, in turn, in single quotes. Yikes. Thank you for your answer of "try a different approach". That made the difference.
Clinton Blackmore
A: 

I always just replace each imbedded single quote with the sequence: '\'' (that is: quote backslash quote quote) which closes the string, appends an escaped single quote and reopens the string. I often whip up a "quotify" function in my Perl scripts to do this for me. The steps would be:

s/'/'\\''/g    # Handle each imbedded quote
$_ = qq['$_']; # Surround result with single quotes.

This pretty much takes care of all cases.

Life gets more fun when you introduce "eval" into your shell-scripts: then you essentially have to re-quotify everything again!

Adrian Pronk
But this isn't perl. And as Steve B pointed out above, with his reference to the "gnu reference manual", you can't escape quotes in bash within the same type of quote. And in fact, don't need to escape them within alternate quotes, e.g. "'" is a valid single-quote string and '"' is a valid double-quote string without requiring any escaping.
nicerobot