Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

My script looks like:

opts="-x ''"
curl http://somepage $opts

I want the string in $opts appended to the command. I use bash -x test.sh to check the expansion and see that the the single-quotes are removed.

If I change it to:

opts="-x \'\'"

After expansion, there are 4 single-quotes.

share|improve this question
    
Are you sure they are actually removed in the unescaped version and not just passed as a blank word? –  Caleb May 9 '11 at 9:46
    
Also, you mention "bash" in your subject and tag, but named your script ".sh", then say you executed it manually with bash. I got different results doing this in bash 4.2.0. Are you sure you are actually using bash and not some other shell with bash emulation? –  Caleb May 9 '11 at 9:50
    
@Caleb: If bash <file> is used, then it is bash, irrespective of filename. (I have yet to see a shell that emulates 'bash' down to providing a binary with the same name...) –  grawity May 10 '11 at 20:22
    
@grawity: Actually there are several that do, most notably busybox. However the main point was that, because his question had mix and match bits, I wanted to make sure the asker understood that he was being ambiguous because you can easily hit inconsistencies if you don't understand that different shells act differently and sh and bash aren't the same. –  Caleb May 11 '11 at 0:04

2 Answers 2

up vote 4 down vote accepted

What exactly do you see? With the script

opts="-x ''"
echo curl http://somepage $opts
opts="-x \'\'"
echo curl http://somepage $opts

With bash 3.2.39 or 4.1.5, I see

+ opts='-x '\'''\'''
+ echo curl http://somepage -x ''\'''\'''
curl http://somepage -x ''
+ opts='-x \'\''\'\'''
+ echo curl http://somepage -x '\'\''\'\'''

The first call to curl (well, echo curl) has a last argument consisting of two characters ''. The trace escapes special characters: ' appears as '\'' (a common idiom to “escape” single quotes inside single quotes). Formally, ''\'''\''' consists of an empty single-quoted string '' followed by the backslash-quoted character \', then again '', again \', and a final ''. (Ksh shows this as the slightly more readable $'\'\''.) The second call passes four characters \'\'.

Under the normal sh parsing rules, you can't make an empty argument by expanding an unquoted variable. Word splitting cuts only where there's a non-whitespace or quoted character.

Since you're using bash, you can put multiple options in an array. This also works in ksh and zsh.

opts=(-x "")
curl http://somepage "${opts[@]}"

For this particular case, you can override the environment variable instead.

http_proxy= curl http://somepage
share|improve this answer
1  
+1 for using arrays. If they're available, it's insanity to use anything else. Compare the first part of this answer with the simplicity of the array solution. –  camh May 9 '11 at 12:22

This is because what you want is to pass a literal empty string to curl, but what you get is a set of literal quotes since they are already quoted. One reference points to another which simply recommends using a function:

download(){
    curl http://somepage "$@"
}
download -x ''

If you want to observe what your script is actually doing, try running set -x before it.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.