I've recently discovered that you can't pass a null string to a Bash array. This is tricky, as I'm trying to insert an empty string value into an array.
I've noticed that the Bash completion variable COMP_WORDS, however, can contain an empty value.
I've written a dummy completion script to illustrate this, with the debugging options on:
1 #!/bin/bash 2 _comp() { 3 set -xv 4 for i in ${!COMP_WORDS[@]}; do 5 echo "<${COMP_WORDS[$i]}>" 6 done 7 set +xv 8 local cur=${COMP_WORDS[$COMP_CWORD]} 9 10 local arr=(apple banana mango pineapple) 11 COMPREPLY=() 12 COMPREPLY=($(compgen -W "${arr[*]}" -- $cur)) 13 14 } 15 16 complete -F _comp dummy
If I source this file, and then enter the following:
dummy apple banana
And then if I move the cursor back to the middle space between apple and banana (indicated below by an underscore) ...
dummy apple _ banana
And then if I hit tab, I get the following output from the resulting debug, showing four array elements, 'dummy' 'apple' '' 'banana'
for i in '${!COMP_WORDS[@]}' + echo '<dummy>' <dummy> + for i in '${!COMP_WORDS[@]}' + echo '<apple>' <apple> + for i in '${!COMP_WORDS[@]}' + echo '<>' <> + for i in '${!COMP_WORDS[@]}' + echo '<banana>' <banana>
So the COMP_WORDS array is clearly capable of storing a null string of some kind. Although interestingly, this does not happen if I use a regular for loop, accessing the array elements rather than the indices. I.e., if I change the for loop in the debug section to this ...
for i in ${COMP_WORDS[@]}; do echo "<$i>" done
Then I get the following debug output showing only three array elements: 'dummy' 'apple' 'banana'
for i in '${COMP_WORDS[@]}' + echo '<dummy>' <dummy> + for i in '${COMP_WORDS[@]}' + echo '<apple>' <apple> + for i in '${COMP_WORDS[@]}' + echo '<banana>' <banana>
And I've tried echoing the length of the array with ${#COMP_WORDS[@]}
- for this input, it shows a length of four. So it clearly does contain four elements, one being a null string.
This seems like really strange behaviour to me. My question is twofold:
What is the explanation for the COMP_WORDS array being able to store null strings when normal arrays apparently cannot?
Why am I unable to see the null string when I use a regular for loop, but I can see it when I access the elements of the array by their indices?
\0
;arr=( "" "" "" ); echo ${#arr[@]}
, result3
for i in "${COMP_WORDS[@]}"; do