Bash Parameter and Variable Expansion: Difference between revisions
(48 intermediate revisions by the same user not shown) | |||
Line 18: | Line 18: | ||
10 | 10 | ||
${a | ${a} | ||
=Difference between $ and ${...}= | =Difference between $ and ${...}= | ||
<font color=darkgray>TODO</font> | <font color=darkgray>TODO</font> | ||
==${...?}== | |||
This syntax fails the command if the variable referred between { and ?} does not exist: | |||
<syntaxhighlight lang='text'> | |||
echo ${NO_SUCH_VAR?} | |||
-bash: NO_SUCH_VAR: parameter not set | |||
</syntaxhighlight> | |||
=Expand to a Default Value= | =Expand to a Default Value= | ||
{{External|http://wiki.bash-hackers.org/syntax/pe#use_a_default_value}} | {{External|http://wiki.bash-hackers.org/syntax/pe#use_a_default_value}} | ||
{{External|https://unix.stackexchange.com/questions/122845/using-a-b-for-variable-assignment-in-scripts/122878}} | |||
<syntaxhighlight lang='bash'> | <syntaxhighlight lang='bash'> | ||
Line 51: | Line 60: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
This expression works like [[#Expand_to_a_Default_Value|expansion to a default value]], but the word is not only expanded, but also '''assigned''' to the variable, if it was unset or null. The first form work if the variable is unset or an empty string, the second only if the parameter was unset. | This expression works like [[#Expand_to_a_Default_Value|expansion to a default value]], but the word is not only expanded, but also '''assigned''' to the variable, if it was unset or null. | ||
The first form <code>:=</code> work if the variable is unset or an empty string, the second <code>=</code> only if the parameter was unset. | |||
=Use an Alternate Value= | =Use an Alternate Value= | ||
Line 60: | Line 71: | ||
${var:+alternative} | ${var:+alternative} | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Example: | |||
<syntaxhighlight lang='bash'> | |||
LD_LIBRARY_PATH="$JAVA_HOME/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" | |||
</syntaxhighlight> | |||
This form expands to nothing if the parameter is unset or empty. | This form expands to nothing if the parameter is unset or empty. | ||
Line 75: | Line 92: | ||
{{Internal|envsubst#Overview|envsubst}} | {{Internal|envsubst#Overview|envsubst}} | ||
=String Length= | =<span id='String_Length'></span>String Length ${#var}= | ||
The length of a variable's value: | The length of a variable's value: | ||
Line 82: | Line 99: | ||
${#var} | ${#var} | ||
</syntaxhighlight> | </syntaxhighlight> | ||
If the first character of parameter is an exclamation point (!), a level of variable indirection is introduced. Bash uses the value of the variable | =<span id='Indirect_Expansion'></span><span id='Variable_Indirection'></span><span id='.24.21..._Variable_Indirection.2C_Indirect_Expansion'></span>$!... Indirect Variables, Variable Indirection, Indirect Expansion= | ||
If the first character of parameter is an exclamation point (!), a level of variable indirection is introduced. Bash uses the value of the variable indicated by the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion. The exceptions to this are the expansions of ${!prefix*} and ${!name[@]} described below. The exclamation point must immediately follow immediately after the left brace in order to introduce indirection. Example: | |||
<syntaxhighlight lang="bash"> | |||
# 'a' is the indirect variable, that contains the name of the actual variable, b: | |||
a="b" | |||
b="blah" | |||
echo ${!a} | |||
</syntaxhighlight> | |||
produces "blah". | produces "blah". | ||
==Assignment to Indirect Variables== | |||
Values can be assigned to an indirect variable with the following syntactic pattern: | |||
<syntaxhighlight lang="bash"> | |||
eval "${indirect_variable_name}=value" | |||
</syntaxhighlight> | |||
or even: | |||
<syntaxhighlight lang="bash"> | |||
eval "${indirect_variable_name}=\"value\"" | |||
</syntaxhighlight> | |||
As such, | |||
<syntaxhighlight lang="bash"> | |||
a="b" | |||
eval "${a}=blah" | |||
echo ${b} | |||
</syntaxhighlight> | |||
produces "blah". | |||
It seems that under some circumstances it is possible to assign a value to an indirect variable simply using ${indirect_variable_name}=value syntax, but this seems to fail with bash 4 and 5: | |||
<syntaxhighlight lang="bash"> | |||
a="b" | |||
${a}="blah" | |||
b=blah: command not found | |||
</syntaxhighlight> | |||
In each of the cases below, word is subject to tilde expansion, parameter expansion, command substitution, and arithmetic expansion. | In each of the cases below, word is subject to tilde expansion, parameter expansion, command substitution, and arithmetic expansion. | ||
When not performing substring expansion, using the forms documented below, bash tests for a parameter that is unset or null. Omitting the colon results in a test only for a parameter that is unset. | When not performing substring expansion, using the forms documented below, bash tests for a parameter that is unset or null. Omitting the colon results in a test only for a parameter that is unset. | ||
==Indirect Variable Access for Indexed Arrays== | |||
{{Internal|Bash_Arrays#Indirect_Variable_Access_for_Indexed_Arrays|Bash Arrays - Indirect Variable Access for Indexed Arrays}} | |||
==Indirect Variable Access for Associative Arrays== | |||
{{Internal|Bash_Arrays#Indirect_Variable_Access_for_Associative_Arrays|Bash Arrays - Indirect Variable Access for Associative Arrays}} | |||
=Quoted String Expansion $'...'= | =Quoted String Expansion $'...'= | ||
Line 142: | Line 195: | ||
produces "hi" | produces "hi" | ||
=Replace | ==Last Character of a String== | ||
All of the examples below use [[Bash Patterns|bash patterns]]. The pattern format is described in {{Internal|Bash Patterns|bash Patterns}} | |||
Negative indices count from the end of the string, so the last character is: | |||
<syntaxhighlight lang='bash'> | |||
s="something" | |||
result=${s: -1} | |||
</syntaxhighlight> | |||
produces "g" | |||
{{Warn|The space after the colon is '''required''' otherwise the expression will silently fail to evaluate and return the whole string.}} | |||
=<span id='Replace_Strings_in_Place'></span>Replace Substrings= | |||
==bash Patterns and Regular Expressions== | |||
All of the examples below use [[Bash Patterns|bash patterns]]. The pattern format is described in {{Internal|Bash Patterns|bash Patterns}} | |||
==Replace Beginning== | ==Replace Beginning== | ||
Line 149: | Line 217: | ||
${var_name/#pattern/replacement} | ${var_name/#pattern/replacement} | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Example: | Example: | ||
<syntaxhighlight lang='bash'> | <syntaxhighlight lang='bash'> | ||
Line 160: | Line 226: | ||
==Replace End== | ==Replace End== | ||
<syntaxhighlight lang='bash'> | |||
${var_name/%pattern/replacement} | |||
</syntaxhighlight> | |||
==Replace First Match== | ==Replace First Match== | ||
<syntaxhighlight lang='bash'> | |||
${var_name/pattern/replacement} | |||
</syntaxhighlight> | |||
==Replace All Matches== | ==Replace All Matches== | ||
<syntaxhighlight lang='bash'> | |||
${var_name//pattern/replacement} | |||
</syntaxhighlight> | |||
Application: [[Bash Determine whether a Variable Contains Spaces#Method_1|determine whether a variable contains spaces]]. | |||
Conversion of a comma-separated list to a space-separated list: | |||
<syntaxhighlight lang='bash'> | |||
${var_name//,/ } | |||
</syntaxhighlight> | |||
=Delete Substrings= | |||
==Delete from the Front of the String== | |||
===Delete Shortest Matching Leading String=== | |||
The following syntax deletes the ''shortest'' matching string from the front of the given string. | |||
<syntaxhighlight lang='bash'> | |||
${var_name#pattern} | |||
</syntaxhighlight> | |||
Example: | |||
<syntaxhighlight lang='bash'> | |||
s="something" | |||
echo ${s#s*e} | |||
</syntaxhighlight> | |||
produces "thing". | |||
More details about bash patterns:{{Internal|Bash_Patterns|bash patterns}} | |||
===Delete Longest Matching Leading String=== | |||
<syntaxhighlight lang='bash'> | |||
${var_name##pattern} | |||
</syntaxhighlight> | |||
Trimming leading spaces: [[Bash Trim|trim]]. | |||
More details about bash patterns:{{Internal|Bash_Patterns|bash patterns}} | |||
==Delete from the Back of the String== | |||
===Delete Shortest Matching Trailing String=== | |||
The following syntax deletes the ''shortest'' matching string from the back of the given string. | |||
<syntaxhighlight lang='bash'> | |||
${var_name%pattern} | |||
</syntaxhighlight> | |||
Example: | |||
<syntaxhighlight lang='bash'> | |||
s="something" | |||
echo ${s%t*g} | |||
</syntaxhighlight> | |||
produces "some". | |||
===Delete Longest Matching Trailing String=== | |||
<syntaxhighlight lang='bash'> | |||
${var_name%%pattern} | |||
</syntaxhighlight> | |||
Trimming trailing spaces: {{Internal|Bash Trim|bash trim}} | |||
==Delete Characters with <tt>tr</tt>== | |||
{{Internal|Tr#-d|<tt>tr -d</tt>}} | |||
=To Uppercase= | |||
Other approaches: using [[tr]]. | |||
==First Character== | |||
<syntaxhighlight lang='bash'> | |||
${var_name^} | |||
</syntaxhighlight> | |||
==All Characters== | |||
<syntaxhighlight lang='bash'> | |||
${var_name^^} | |||
</syntaxhighlight> | |||
=To Lowercase= | |||
Other approaches: using [[tr]]. | |||
==First Character== | |||
<syntaxhighlight lang='bash'> | |||
${var_name,} | |||
</syntaxhighlight> | |||
==All Characters== | |||
<syntaxhighlight lang='bash'> | |||
${var_name,,} | |||
</syntaxhighlight> |
Latest revision as of 04:33, 3 March 2023
Internal
Overview
A dollar sign ($) that is NOT followed by an open parenthesis initiates parameter or variable expansion, which is a particular case of command line expansion. The simplest case of parameter expansion is retrieving the parameter value: the associated value is retrieved by prefixing the parameter's number, character or name with $ or enclosing it in ${...}.
Parameters and variables are not expanded if the string they are included in are enclosed within single quotes or if the leading dollar sign is escaped. Parameters and variables are expanded if the string they are included in is enclosed within double quotes.
a=10 echo "${a}" echo '${a}'
produces
10 ${a}
Difference between $ and ${...}
TODO
${...?}
This syntax fails the command if the variable referred between { and ?} does not exist:
echo ${NO_SUCH_VAR?}
-bash: NO_SUCH_VAR: parameter not set
Expand to a Default Value
${var:-alternative}
The :- form : if the variable 'var' referred in the expression was not defined, or it is the empty string, the expression expands the alternative.
${var-alternative}
The - form: if the colon is omitted, the expression is expanded to the alternative value only if the variable is not defined, not when it was empty.
Assign a Default Value
${var:=word}
${var=word}
This expression works like expansion to a default value, but the word is not only expanded, but also assigned to the variable, if it was unset or null.
The first form :=
work if the variable is unset or an empty string, the second =
only if the parameter was unset.
Use an Alternate Value
${var:+alternative}
Example:
LD_LIBRARY_PATH="$JAVA_HOME/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
This form expands to nothing if the parameter is unset or empty.
${var+alternative}
This form expands to nothing if the variable is unset, and to the alternative if the variable is empty.
Variable Expansion in an Arbitrary File
If an arbitrary text file contains environment variable declarations, they can be expanded with envsubst. No other shell command line expansions will be performed. More details:
String Length ${#var}
The length of a variable's value:
${#var}
$!... Indirect Variables, Variable Indirection, Indirect Expansion
If the first character of parameter is an exclamation point (!), a level of variable indirection is introduced. Bash uses the value of the variable indicated by the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion. The exceptions to this are the expansions of ${!prefix*} and ${!name[@]} described below. The exclamation point must immediately follow immediately after the left brace in order to introduce indirection. Example:
# 'a' is the indirect variable, that contains the name of the actual variable, b:
a="b"
b="blah"
echo ${!a}
produces "blah".
Assignment to Indirect Variables
Values can be assigned to an indirect variable with the following syntactic pattern:
eval "${indirect_variable_name}=value"
or even:
eval "${indirect_variable_name}=\"value\""
As such,
a="b"
eval "${a}=blah"
echo ${b}
produces "blah".
It seems that under some circumstances it is possible to assign a value to an indirect variable simply using ${indirect_variable_name}=value syntax, but this seems to fail with bash 4 and 5:
a="b"
${a}="blah"
b=blah: command not found
In each of the cases below, word is subject to tilde expansion, parameter expansion, command substitution, and arithmetic expansion.
When not performing substring expansion, using the forms documented below, bash tests for a parameter that is unset or null. Omitting the colon results in a test only for a parameter that is unset.
Indirect Variable Access for Indexed Arrays
Indirect Variable Access for Associative Arrays
Quoted String Expansion $'...'
This construct expands single or multiple escaped octal or hex values into ASCII or Unicode characters.
The following are equivalent:
$'\012' # Octal value $'\x0a' # Hexadecimal value $'\n'
Example:
echo "something"$'\047'"something else"$'\047'
The octal and hexadecimal values for ASCII characters are available here:
Extract Substrings
Extract a Substring from a Certain Position
Specify the index of the first character of the substring. Indices are 0-based. The substring will extend the end of the original string.
There is no need to de-reference the variable that contains the index in ${s:i}, though ${s:${i}} will also work.
s="something"
i=4
result=${s:i}
produces "thing"
Extract a Substring of a Certain Length from a Certain Position
Specify the index of the first character of the substring and the length of the string to extract. Indices are 0-based.
There is no need to de-reference the variable that contains the index in ${s:i}, though ${s:${i}} will also work.
s="something"
i=5
len=2
result=${s:i:len}
produces "hi"
Last Character of a String
Negative indices count from the end of the string, so the last character is:
s="something"
result=${s: -1}
produces "g"
The space after the colon is required otherwise the expression will silently fail to evaluate and return the whole string.
Replace Substrings
bash Patterns and Regular Expressions
All of the examples below use bash patterns. The pattern format is described in
Replace Beginning
${var_name/#pattern/replacement}
Example:
s="something"
echo ${s/#s*e/other}
produces "otherthing".
Replace End
${var_name/%pattern/replacement}
Replace First Match
${var_name/pattern/replacement}
Replace All Matches
${var_name//pattern/replacement}
Application: determine whether a variable contains spaces.
Conversion of a comma-separated list to a space-separated list:
${var_name//,/ }
Delete Substrings
Delete from the Front of the String
Delete Shortest Matching Leading String
The following syntax deletes the shortest matching string from the front of the given string.
${var_name#pattern}
Example:
s="something"
echo ${s#s*e}
produces "thing".
More details about bash patterns:
Delete Longest Matching Leading String
${var_name##pattern}
Trimming leading spaces: trim.
More details about bash patterns:
Delete from the Back of the String
Delete Shortest Matching Trailing String
The following syntax deletes the shortest matching string from the back of the given string.
${var_name%pattern}
Example:
s="something"
echo ${s%t*g}
produces "some".
Delete Longest Matching Trailing String
${var_name%%pattern}
Trimming trailing spaces:
Delete Characters with tr
To Uppercase
Other approaches: using tr.
First Character
${var_name^}
All Characters
${var_name^^}
To Lowercase
Other approaches: using tr.
First Character
${var_name,}
All Characters
${var_name,,}