Search code examples
shellscriptingsplitzsh

Zsh - split string by spaces when using dot operator


Here is my script:

#/bin/bash
list="a b c"
for i in $list; do
  echo $i
done

This works:

➜  ~  ./lol.sh 
a
b
c

This doesn't:

➜  ~  . ./lol.sh 
a b c

Why split does not work with dot command and how can I fix it?


Solution

  • Lists should never be represented as strings. Use array syntax.

    list=( a b c )
    for i in "${list[@]}"; do
      echo "$i"
    done
    

    There are several reasons this is preferable.

    In ZSH:

    • ZSH breaks POSIX by not performing string-splitting at all on unquoted expansions unless they explicitly request it. You can make this request by either running setopt sh_word_split, or using the parameter expansions ${=list} or ${(ps: :)list}

    In other Bourne-derived shells:

    • String-splitting is dependent on the value of IFS, which cannot be guaranteed to be at defaults, especially when sourced from a separate script (which may have changed it locally).
    • Unquoted expansion also performs globbing, which can have different results depending on which files are in the current working directory (for instance, if your list contains hello[world], this will behave in an unexpected manner if your current directory contains files named hellow, helloo, or otherwise matching the glob).
    • Avoiding the globbing step is not only more correct, but also more efficient.