# Bash Shell Parameter Expansion

The basic form of parameter expansion is \${parameter}. The value of parameter is substituted.

## Indirect expansion

If the first character of parameter is an exclamation point (`!`), and parameter is not a nameref, it introduces a level of variable indirection. Bash uses the value of the variable formed from 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.

If parameter is a nameref, this expands to the name of the variable referenced by parameter instead of performing the complete indirect expansion. The exceptions to this are the expansions of `\${!prefix*}` and `\${!name[@]}` described below. The exclamation point must immediately follow the left brace in order to introduce indirection.

``````\$ NAME="VARIABLE"
\$ VARIABLE=42
\$ echo \${!NAME}
42
``````

## Expansion list

• \${parameter:-word}

If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.

• \${parameter:=word}

If parameter is unset or null, the expansion of word is assigned to parameter. The value of parameter is then substituted. Positional parameters and special parameters may not be assigned to in this way.

• \${parameter:?word}

If parameter is null or unset, the expansion of word (or a message to that effect if word is not present) is written to the standard error and the shell, if it is not interactive, exits. Otherwise, the value of parameter is substituted.

• \${parameter:+word}

If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.

• \${parameter:offset}

• \${parameter:offset:length}

This is referred to as Substring Expansion. It expands to up to length characters of the value of parameter starting at the character specified by offset. If parameter is `@`, an indexed array subscripted by `@` or `*`, or an associative array name, the results differ as described below. If length is omitted, it expands to the substring of the value of parameter starting at the character specified by offset and extending to the end of the value. length and offset are arithmetic expressions (see Shell Arithmetic).

If offset evaluates to a number less than zero, the value is used as an offset in characters from the end of the value of parameter. If length evaluates to a number less than zero, it is interpreted as an offset in characters from the end of the value of parameter rather than a number of characters, and the expansion is the characters between offset and that result. Note that a negative offset must be separated from the colon by at least one space to avoid being confused with the `:-` expansion.

``````\$ string=01234567890abcdefgh
\$ echo \${string:7}
7890abcdefgh
\$ echo \${string:7:2}
78
\$ echo \${string:7:-2}
7890abcdef
\$ echo \${string: -7}
bcdefgh
\$ set -- 01234567890abcdefgh
\$ echo \${1:7}
7890abcdefgh
\$ array=01234567890abcdefgh
\$ echo \${array:7}
7890abcdefgh
``````

If parameter is `@`, the result is length positional parameters beginning at offset. A negative offset is taken relative to one greater than the greatest positional parameter, so an offset of -1 evaluates to the last positional parameter. It is an expansion error if length evaluates to a number less than zero.

``````\$ set -- 1 2 3 4 5 6 7 8 9 0 a b c d e f g h
\$ echo \${@:7}
7 8 9 0 a b c d e f g h
\$ echo \${@:7:2}
7 8
\$ echo \${@:7:-2}
bash: -2: substring expression < 0
\$ echo \${@: -7:2}
b c
\$ echo \${@:0}
./bash 1 2 3 4 5 6 7 8 9 0 a b c d e f g h
\$ echo \${@:0:2}
./bash 1
``````

If parameter is an indexed array name subscripted by `@` or `*`, the result is the length members of the array beginning with `\${parameter[offset]}`. A negative offset is taken relative to one greater than the maximum index of the specified array. It is an expansion error if length evaluates to a number less than zero.

``````\$ array=(0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h)
\$ echo \${array[@]:7}
7 8 9 0 a b c d e f g h
\$ echo \${array[@]:7:2}
7 8
\$ echo \${array[@]: -7:2}
b c
\$ echo \${array[@]: -7:-2}
bash: -2: substring expression < 0
\$ echo \${array[@]:0}
0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h
\$ echo \${array[@]:0:2}
0 1
\$ echo \${array[@]: -7:0}
``````

Substring indexing is zero-based unless the positional parameters are used, in which case the indexing starts at 1 by default. If offset is 0, and the positional parameters are used, \$@ is prefixed to the list.

• \${!prefix*}

• \${!prefix@}

Expands to the names of variables whose names begin with prefix, separated by the first character of the `IFS` special variable. When `@` is used and the expansion appears within double quotes, each variable name expands to a separate word.

• \${!name[@]}

• \${!name[*]}

If name is an array variable, expands to the list of array indices (keys) assigned in name. If name is not an array, expands to 0 if name is set and null otherwise. When `@` is used and the expansion appears within double quotes, each key expands to a separate word.

• \${#parameter}

The length in characters of the expanded value of parameter is substituted. If parameter is `*` or `@`, the value substituted is the number of positional parameters. If parameter is an array name subscripted by `*` or `@`, the value substituted is the number of elements in the array. If parameter is an indexed array name subscripted by a negative number, that number is interpreted as relative to one greater than the maximum index of parameter, so negative indices count back from the end of the array, and an index of -1 references the last element.

• \${parameter#word}

• \${parameter##word}

The word is expanded to produce a pattern just as in filename expansion (see Filename Expansion). If the pattern matches the beginning of the expanded value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the `#` case) or the longest matching pattern (the `##` case) deleted.

If parameter is `@` or `*`, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with `@` or `*`, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.

• \${parameter%word}

• \${parameter%%word}

The word is expanded to produce a pattern just as in filename expansion. If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the value of parameter with the shortest matching pattern (the `%` case) or the longest matching pattern (the `%%` case) deleted.

If parameter is `@` or `*`, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with `@` or `*`, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.

例如对字符串进行分割：

``````STR="test-something"
var1=\${STR%-*}
var2=\${STR#*-}
``````

`\${STR%-*}` deletes the shortest substring of `\$STR` that matches the pattern `-*` starting from the end of the string. `\${STR#*-}` does the same, but with the `*-` pattern and starting from the beginning of the string.

• \${parameter/pattern/string}

The pattern is expanded to produce a pattern just as in filename expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. If pattern begins with `/`, all matches of pattern are replaced with string. Normally only the first match is replaced. If pattern begins with `#`, it must match at the beginning of the expanded value of parameter. If pattern begins with `%`, it must match at the end of the expanded value of parameter. If string is null, matches of pattern are deleted and the `/` following pattern may be omitted. If the nocasematch shell option (see the description of shopt in The Shopt Builtin) is enabled, the match is performed without regard to the case of alphabetic characters. If parameter is `@` or `*`, the substitution operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with `@` or `*`, the substitution operation is applied to each member of the array in turn, and the expansion is the resultant list.

• \${parameter^pattern}

• \${parameter^^pattern}
• \${parameter,pattern}
• \${parameter,,pattern}

This expansion modifies the case of alphabetic characters in parameter. The pattern is expanded to produce a pattern just as in filename expansion. Each character in the expanded value of parameter is tested against pattern, and, if it matches the pattern, its case is converted. The pattern should not attempt to match more than one character. The `^` operator converts lowercase letters matching pattern to uppercase; the `,` operator converts matching uppercase letters to lowercase. The `^^` and `,,` expansions convert each matched character in the expanded value; the `^` and `,` expansions match and convert only the first character in the expanded value. If pattern is omitted, it is treated like a `?`, which matches every character. If parameter is `@` or `*`, the case modification operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with `@` or `*`, the case modification operation is applied to each member of the array in turn, and the expansion is the resultant list.

• \${parameter@operator}

The expansion is either a transformation of the value of parameter or information about parameter itself, depending on the value of operator. Each operator is a single letter:

• Q

The expansion is a string that is the value of parameter quoted in a format that can be reused as input.

• E

The expansion is a string that is the value of parameter with backslash escape sequences expanded as with the \$'…' quoting mechansim.

• P

The expansion is a string that is the result of expanding the value of parameter as if it were a prompt string (see Controlling the Prompt).

• A

The expansion is a string in the form of an assignment statement or declare command that, if evaluated, will recreate parameter with its attributes and value.

• a

The expansion is a string consisting of flag values representing parameter’s attributes.

If parameter is `@` or `*`, the operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with `@` or `*`, the operation is applied to each member of the array in turn, and the expansion is the resultant list.

The result of the expansion is subject to word splitting and pathname expansion as described below.
{"ft_lang_label":"__label__en","ft_lang_prob":0.725769,"math_prob":0.94907737,"size":10624,"snap":"2023-40-2023-50","text_gpt3_token_len":2460,"char_repetition_ratio":0.21704331,"word_repetition_ratio":0.335,"special_character_ratio":0.23983434,"punctuation_ratio":0.10730253,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.953524,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2023-10-02T00:49:50Z\",\"WARC-Record-ID\":\"<urn:uuid:5edca312-243c-42e2-a727-2ca999dd212c>\",\"Content-Length\":\"56188\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:f8a9e569-ca77-4f45-9435-079d6ab073f6>\",\"WARC-Concurrent-To\":\"<urn:uuid:c1cb1dbd-1240-488c-adcc-2c36c5f0c21d>\",\"WARC-IP-Address\":\"176.122.128.108\",\"WARC-Target-URI\":\"https://wiki.zohead.com/%E6%8A%80%E6%9C%AF/Linux/Shell/Bash%20Shell%20Parameter%20Expansion.md\",\"WARC-Payload-Digest\":\"sha1:AIIYKIS5CEHWP5ZOFKRTZQ2EAUV2C6RV\",\"WARC-Block-Digest\":\"sha1:GJ3AWEYXNUX5BQEGHWDIIOT2XYQ4NADJ\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2023/CC-MAIN-2023-40/CC-MAIN-2023-40_segments_1695233510942.97_warc_CC-MAIN-20231002001302-20231002031302-00770.warc.gz\"}"}