6

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?

4
  • 1
    I cannot duplicate your problem using bash 3 or bash 4. What version are you running? Commented Aug 24, 2015 at 15:30
  • 2
    Oh darn. Just realized I use zsh. Commented Aug 24, 2015 at 15:34
  • 1
    ...so, the dot operator isn't actually a factor in this issue, except inasmuch as it changes which shell you're actually running the code in. Straighten out which shell in your environment is which, and you'll have removed it as a factor. Commented Aug 24, 2015 at 15:48
  • I too was having the same issue - in zsh.... Using @CharlesDuffy info ... I modded my script. ```bash Commented Jan 16, 2021 at 1:16

2 Answers 2

12

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.
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, works in bash but zsh says: ./lol.sh: 2: ./lol.sh: Syntax error: "(" unexpected
Are you very, very sure you were testing with ZSH, not /bin/sh? "(" unexpected is exactly what you'd get from dash, ash or similar POSIX shells from that code.
0

Whilst I note the comment regarding lists by Charles Duffy, this was my solution/test.

#!/bin/zsh
function three()
{
        first=$1
        second=$2
        third=$3
        echo "1: $first 2: $second 3:$third"
}

setopt sh_word_split
set "1 A 2" "2 B 3" "3 C 4" "4 D 5"
for i;do
        three $i;

 done

This will output

1: 1 2: A 3:2
1: 2 2: B 3:3
1: 3 2: C 3:4
1: 4 2: D 3:5

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.