${parameter%[word]}
Remove Smallest Suffix Pattern. The word
shall be expanded to produce a pattern. The parameter expansion shall then result in parameter
, with the smallest portion of the suffix matched by the pattern deleted. If present, word
shall not begin with an unquoted %
.
${parameter%%[word]}
Remove Largest Suffix Pattern. The word
shall be expanded to produce a pattern. The parameter expansion shall then result in parameter
, with the largest portion of the suffix matched by the pattern deleted.
${parameter#[word]}
Remove Smallest Prefix Pattern. The word
shall be expanded to produce a pattern. The parameter expansion shall then result in parameter
, with the smallest portion of the prefix matched by the pattern deleted. If present, word
shall not begin with an unquoted #
.
${parameter##[word]}
Remove Largest Prefix Pattern. The word
shall be expanded to produce a pattern. The parameter expansion shall then result in parameter
, with the largest portion of the prefix matched by the pattern deleted.
[emphasis mine]
Source: POSIX documentation. The relevant fragment of Bash Reference Manual: here.
The syntax has nothing to do with arrays.
In particular ${line#* }
expands like $line
but removes the smallest portion matched by *
(asterisk+space, where asterisk matches zero or more characters and space matches space character) from the beginning of it. I.e. it removes characters up to and including the first space from the expansion.
Example:
$ line='foo bar baz'
$ echo "${line#* }"
bar baz
If nothing matches the pattern then nothing will be removed:
$ line='no-match'
$ echo "${line#* }"
no-match
Note ${line#* }
only expands to something that can be different than $line
. Sole usage of ${line#* }
does not redefine the variable:
$ line='foo bar baz'
$ echo "${line#* }"
bar baz
$ echo "$line"
foo bar baz