ditoslav
ditoslav

Reputation: 4872

How to use Bash substitution in a variable declaration 2

How to use Bash substitution in a variable declaration

Some of you may have read the aforementioned question but I have been left with more questions than answer. I tried googling how bash tokenizing -> expansion works in detail but did not find the right answers.

Let's look at simple example:

q="www"
e=$q{.,.,.}
echo $e 
#outputs: www{.,.,.}

Now this does not work as I would expect. Especially since echo $q{.,.,.} outputs www. www. www. as I would expect. There have been some sugestions in the first SO question to write stuff like set $q{.,.,.,1} & s="$@" & echo $s

This does work in the terminal but for some reasons when entered in a .sh script it outputs www{.,.,.}

Why is there a different behaviour between the script and the terminal and how to make sure to trigger the expansion?

Also, why does q=* trigger pathname expansion but q={.,.,.} does not trigger braces expansion?

Upvotes: 0

Views: 51

Answers (3)

user2350426
user2350426

Reputation:

Words in the right-side of an assignment do not: "Brace Expand"

From "man bash" (emphasis mine):

A variable may be assigned to by a statement of the form

         name=[value]

All values undergo tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal

There is no mention of "Brace Expansion", "Pathname expansion" or "splitting".

To get "Brace expansion" make it a command line (note that "$q" is quoted):

$ q="www"
$ e="$( echo "$q"{.,.,.} )"
$ echo "$e" 
www. www. www.

Or if you want an array (s asked in the linked question), use directly:

$ e=( "$q"{.,.,.} )
$ printf '<%s> ' "${e[@]}"; echo         ### No, `$e` is not enough.
<www.> <www.> <www.>  

why does q=* trigger pathname expansion

No, it doesn't:

$ a=* ; echo "$a"
*

Of course, an unquoted $a will undergo pathname expansion, try:

$ a=* ; echo $a

Upvotes: 1

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84343

Scalars Aren't Arrays

To do what you want, you need to assign e as an array. You can then use array expansion to view the contents in the way you expect. Consider the following:

q="www"
e=( $q{.,.,.} )
echo "${e[@]}"

www. www. www.

Upvotes: 2

glenn jackman
glenn jackman

Reputation: 246774

bash performs expansion in a defined order, and brace expansion happens before parameter expansion.

When bash sees echo $e, there are no brace expansions to perform. After the parameter expansion, bash does not go back to the prior ones.

If you need this, you can do one of:

e=$(echo $q{.,.,.}); echo "$e"

e=$q{.,.,.}; eval echo "$e"

Upvotes: 1

Related Questions