1

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:

  1. What is the explanation for the COMP_WORDS array being able to store null strings when normal arrays apparently cannot?

  2. 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?

4
  • empty string is not Null\0; arr=( "" "" "" ); echo ${#arr[@]}, result 3CommentedDec 3, 2020 at 17:10
  • Ah okay. So then I'm wondering - why can I not access these elements using an ordinary for loop?
    – Lou
    CommentedDec 3, 2020 at 17:21
  • 1
    @Lou If you expand the array without double-quotes, word splitting will effectively remove any null elements (and mangle any containing whitespace, and possibly other things). So use for i in "${COMP_WORDS[@]}"; doCommentedDec 3, 2020 at 17:30
  • 1
    Thanks, that makes sense! I must remember to quote everything it seems.
    – Lou
    CommentedDec 3, 2020 at 17:34

1 Answer 1

5

You seem to be confusing the empty string "" with the NULL character \0. They are not the same. You can use empty strings in arrays and variables:

$ a=(aa "" "b") $ echo "${#a[@]}" 3 $ printf -- '- %s\n' "${a[@]}" - aa - - b $ for i in "${a[@]}"; do > printf '%s\n' "$i" > done aa b 

Some of the conditional expressions in Bash even allow testing whether a string is empty:

-z string

True if the length of string is zero. 

-n string string

True if the length of string is non-zero. 

See also When is double-quoting necessary?

4
  • Oh right, okay. So I guess the question then becomes, why can't I access empty strings in arrays using a regular for loop?
    – Lou
    CommentedDec 3, 2020 at 17:15
  • 2
    You can, you just have to quote the reference to the array in the loop header ("${a[@]}" instead of ${a[@]}).
    – Wieland
    CommentedDec 3, 2020 at 17:26
  • Ah, thanks! Still taking me a while to wrap my head around Bash.
    – Lou
    CommentedDec 3, 2020 at 17:29
  • 2
    If you're new to bash (or, well, even if you're not :-) ), you can use shellcheck.net to check your script for any of the common errors. It's a really valuable tool.
    – Wieland
    CommentedDec 3, 2020 at 17:30

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.