My attempts seem to overcomplicate such an easy task
The task might look easy, but might not be a common use case and therefore have no syntactic sugar to make it easy, especially if you can use other built-in features to accomplish it.
You have plenty of alternatives, here's one more:
put_first_index_in () {
printf -v "${1?}" "%s" "${2?}"
}
put_first_index_in first_index "${!arr[@]}"
What is actually happening in ${!arr[@]:0:1}?
Indirect variable 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.
With ! as the first character, three possible things are supported: ${!parameter} (the indirect expansion given above), ${!prefix*}, ${!prefix@} (expand to variable names matching the prefix), and ${!name[*]}, ${!name[@]} (expand to indexes of the name array).
The docs suggest that only ${!parameter} supports further substitution, since it is only mentioned for this and not for the others. So bash tries to do the following:
- Expand
arr[@]
- Apply indirect expansion on the string obtained from (1)
- Get the
0:1 substring from the string obtained from indirect expansion
Since is not a valid character in identifiers, we get that error:
$ foo=SHELL
$ echo ${!foo}
/bin/zsh
$ echo ${!foo:0:1}
/
$ foo="SHELL "
$ echo ${!foo}
bash: SHELL : bad substitution
$ arr=([2]=SHELL bbb ccc ddd)
$ echo ${!arr[@]:0:1}
bash: SHELL bbb ccc ddd: bad substitution
Thus, this will only work with arrays of a single element, say:
$ arr=([2]=SHELL)
And as expected:
$ echo ${!arr[@]:0:1}
/
first_index=${!arr[@]}approach, make it[*]instead so you're asking for a string explicitly, rather than asking for an array and coercing it into a string. In either case, you'll want to make sure the value of IFS is known.index, either:for first_index in "${!arr[@]}"; do break; donesubst.c; the people who are best equipped to do it live at [email protected]... though a question asking about syntax should go through [email protected] first).arr=([2]=aaa bbb ccc ddd); index=(${!arr[@]}); echo ${index[0]}?