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