LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Variable Substitution (https://www.linuxquestions.org/questions/programming-9/variable-substitution-875246/)

theKbStockpiler 04-15-2011 04:48 PM

Variable Substitution
 
I'm trying to understand just about anyting about BASH Variable Substitution. The part I'm reading is here. ://freebooks.by.ru/view/ShellProgIn24h/31480057.htm So as I don't break forum rules and am not going to contact the publisher put a http in front of the colon.

Any info will be appreciated!

Didier Spaier 04-15-2011 05:02 PM

What is your question?

theKbStockpiler 04-15-2011 05:15 PM

I don't know
 
I don't even understand enough of it to ask a questions except What is it and Why would you use it?


Is it like over-riding a variable so if you don't over-ride it, it goes to the default value?

Edit: I think it just hit me. It substitutes the name of a variable so when you call that particular varible (parameter in the guides words) you are acutually calling a differernt variable that holds a different value?

Nominal Animal 04-15-2011 10:17 PM

I'd recommend reading the Shell Expansions section in the Bash Reference Manual instead.

Here is a trivial example on substitution:

I needed a script that searches files in the directories I specify, or all filesystems (starting at root /) if I don't specify any directories.
Normally, if you don't give any paths to find, it starts the search at the current directory.

You could use
Code:

#!/bin/bash
if [ $# -gt 0 ]; then
    find "$@" -type f
else
    find / -type f
fi

or similar if-then-else constructs, but you do not have to, since
Code:

#!/bin/bash
find "${@:-/}" -type f

does the exact same thing using substitution.

Here, $@ is the special variable that expands to all parameters given on the command line, and $# expands to the number of parameters specified on the command line. They work just like all other shell variables, they just have funny names.

${variable:-value} expands to the value of variable, if the value is not empty. Otherwise it will expand to value.

Other substitutions I've used often are ${variable##pattern}, where pattern is a glob pattern (similar to file name patterns). The longest initial match (if any) is removed from the value of variable. I also use # for the shortest initial match, % for the shortest final match, and %% for the longest final match a lot.

Here's another real life example, this time a lot more complex:

For example, assume you have
Code:

pair="the name field = the value field"
which you wish to parse to a name and a value, converting all linear whitespace to single spaces, and trimming whitespace from both name and value. The usual answer is to use sed:
Code:

name="`echo "$pair" | sed -e 's|[\t\n\v\f\r ]\+| |g; s|^ *\([^=]*[^= ]\) *=.*$|\1|g'`"
value="`echo "$pair" | sed -e 's|[\t\n\v\f\r ]\+| |g; s|^[^=]*= *||'`"

but you can also do it directly in Bash, using variable substitutions:
Code:

LWS="`echo -ne '\t\n\v\f\r '`"

name="${pair//[$LWS]/ }"        # Convert whitespaces to spaces
name="${name//    / }"                # Combine whitespaces
name="${name//  / }"                # Combine whitespaces
name="${name//  / }"                # Combine whitespaces
value="${name#*=}"                # Copy pair with name removed to value
name="${name%%=*}"                # Remove value part from name
value="${value# }"                # Remove leading space from value
value="${value% }"                # Remove trailing space from value
name="${name# }"                # Remove leading space from name
name="${name% }"                # Remove trailing space from value

I run a number of tests on my x86-64 machine (doing the above conversions in a Bash loop). The sed method takes about 7.5ms per pair, but the substitution method takes only about 0.6ms per pair. If you work with say a large configuration file, using substitutions instead of sed cuts the running time to one tenth!

Personally I also like how the parameter substitutions are easy to comment. (It is possible to comment sed patterns, too, but I find it messy.)

theKbStockpiler 04-15-2011 10:41 PM

Ah.. Thanks so much Nominal Animal for the indepth explanation!
 
First time I have printed out a LQ reply on paper so it would be easier to go over.:hattip: Your efforts are worth a tree!

theKbStockpiler 04-15-2011 11:01 PM

A few additional questions.
 
Quote:

${variable:-value} expands to the value of variable, if the value is not empty. Otherwise it will expand to value.
How can "value" expand unless it is a variable? It looks like it is an expression in which "Value" is both a Variable name and a Varable value.

Thanks in advance!

Nominal Animal 04-16-2011 12:17 AM

Quote:

Originally Posted by theKbStockpiler (Post 4326037)
How can "value" expand unless it is a variable?

It does not. value is just a value, not a variable.

Let me reiterate:

expression ${foo:-bar} will expand to the value of variable foo, if variable foo is set and not empty. Otherwise, the expression will expand to bar.

Note that bar is not a variable, it is a string value. If you want the expression to expand to the value of variable var if variable foo is unset or empty, then you use expression ${foo:-$var}.

You can chain the expressions, too. ${foo:-${bar:-${baz:-Nothing at all}}} is completely valid, and will expand to the value of variable foo. If foo is unset or empty, the expression will expand to the value of variable bar. If foo and bar are both unset or empty, the expression will expand to the value of variable baz. If variable baz is also unset or empty, the expression will expand to the string Nothing at all.

grail 04-16-2011 02:21 AM

Another reference as well to help: http://tldp.org/LDP/abs/html/paramet...stitution.html
I found the examples fairly straight forward and easy to follow.


All times are GMT -5. The time now is 06:44 AM.