Getting the first index of an array

I have an array that is not indexed from 0:

arr=([2]=aaa bbb ccc ddd) 

I need to get the first index of an array. There are many things that I have tried and that work:

 for index in "${!arr[@]}"; do first_index=$index break done 
 first_index=$(awk '{ print $1 }' <<< "${!arr[@]}") 
 first_index=$(cut -d' ' -f1 <<< "${!arr[@]}") 
 first_index=${!arr[@]} first_index=${first_index%% *} 
 ind=("${!arr[@]}") first_index=${ind[@]:0:1} 

What I really wanted to work:

 ${!arr[@]:0:1} 

Given that this syntax works well with ${arr[@]:0:1} arrays and is very clean:

  • Is there a similar, cleaner way to do this for indexes, as well as without external tools, temporary arrays, temporary variables, loops, etc.? My attempts seem to complicate the task too much.
  • What is really happening in ${!arr[@]:0:1} ?
+5
source share
1 answer

My attempts seem to complicate the task too much

A task may look easy, but it cannot be a normal use case and therefore does not have syntactic sugar to simplify it, especially if you can use other built-in functions to complete it.

You have many alternatives, here is another one:

 put_first_index_in () { printf -v "${1?}" "%s" "${2?}" } put_first_index_in first_index "${!arr[@]}" 

What really happens in $ {! arr [@]: 0: 1}?

Indirect expansion of variables :

If the first character of the parameter is an exclamation point ( ! ), And the parameter is not nameref, it enters the level of the Indirect variable. Bash uses the value of a variable formed from the rest of the parameter as the name of the variable; this variable is then expanded, and this value is used in the rest of the substitution, not the value of the parameter itself. This is called indirect expansion .

C ! three possible things are supported as the first character: ${!parameter} (the specified indirect extension), ${!prefix*} , ${ !prefix@ } (expand to the names of the variables corresponding to prefix ), and ${!name[*]} , ${!name[@]} (expand indexes of the name array).

The docs assume that only ${!parameter} supports further substitution, since it is only mentioned for this, and not for others. Therefore, Bash is trying to do the following:

  • Expand arr[@]
  • Apply the indirect extension to the string obtained from (1)
  • Get the substring 0:1 from the string obtained from the indirect extension

As is not a valid character in identifiers, we get this 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 one element, for example:

 $ arr=([2]=SHELL) 

And as expected:

 $ echo ${!arr[@]:0:1} / 
+3
source

Source: https://habr.com/ru/post/1274308/


All Articles