[Gllug] Variable substitutuion in bash

Russell Howe rhowe at wiss.co.uk
Sat Sep 11 22:15:53 UTC 2004


On Sat, Sep 11, 2004 at 10:01:13PM +0100, Dylan wrote:
> $var, ${var}, "$var" and "${var}"
> 
> but always the quotes act as literal characters. When I issue:
> 
> oggenc file.wav -c "TAG=value with spaces"
> 
> I get an ogg file with the tag TAG=value with spaces
> 
> When I set a variable to "TAG=value with spaces" and do:
> 
> oggenc file.wav -c $var
> 
> I get an ogg with the tag "TAG=value
> 
> and then cannot open file errors for file 'with' and 'spaces'.
> 
> It doesn't matter what quotes are used.

I think this is what you need:

export var='TAG=value with spaces'
oggenc file.wav "$var"

You could use double quotes on the first line, but using single quotes
stops the shell doing things like variable expansion and interpreting
other special characters.

Maybe an example will help illustrate:

var="TAG=Value with $dollar sign and `backticks`"
var='TAG=Value with $dollar sign and `backticks`"

In the case of the former, bash (and sh too) will replace $dollar with
the value of the 'dollar' environment variable (probably an empty
string, since it's unlikely to be defined), and will replace `backticks`
with the output of executing the 'backticks' command, which probably
doesn't exist, and will likely cause an error.

Since the latter example uses single quotes, none of this shell
processing is performed, and the $ and ` symbols are included literally
in the value of the variable.

You could achieve the same result with:

var="TAG=Value with \$dollar sign and \`backticks\`"

You could even drop the quotes and escape the spaces:

var=TAG=Value\ with\ \$dollar\ sign\ and\ \`backticks\`

I think you'll agree that the single quote version is much more
readable.

When you use an array, the special construct "${arrayname[@]}" (every
bit is important, including the quotes) expands to something like:

"$arrayname[0]" "$arrayname[1]" ... "$arrayname[n]"

Whereas "${arrayname[*]}" would expand to:

$arrayname[0] $arrayname[1] ... $arrayname[n]

Where $arrayname[n] is element number n in the array.

The bash man page is pretty well written, and looking at various scripts
while using it as a reference makes for quite a good learning experience

Take a look at what this does, for example: "${var//foo/bar}" or
"${var%.png}.jpg"

As an example of the latter, consider the effect of this:

for file in *.jpg; do
	convert "$file" "${file%.jpg}.png" && rm -f "$file"
done

-- 
Russell Howe       | Why be just another cog in the machine,
rhowe at siksai.co.uk | when you can be the spanner in the works?
-- 
Gllug mailing list  -  Gllug at gllug.org.uk
http://lists.gllug.org.uk/mailman/listinfo/gllug




More information about the GLLUG mailing list