Tangled syntax error near unexpected done token

I'm trying to learn shell scripts, so I created a simple script with a loop that does nothing:

#!/bin/bash names=(test test2 test3 test4) for name in ${names[@]} do #do something done 

however, when I run this script, I get the following errors:

./test.sh: line 6: syntax error near unexpected token completed

. /test.sh: line 6: done '

What did I miss here? "tab" scripts "shell scripts ??

+6
source share
6 answers

No, shell scripts are not sensitive to the tab (unless you are doing something really crazy, which you are not doing in this example).

You cannot have an empty while do done block (comments are not taken into account) Try replacing echo $name instead

 #!/bin/bash names=(test test2 test3 test4) for name in ${names[@]} do printf "%s " $name done printf "\n" 

Exit

 test test2 test3 test4 
+5
source

dash and bash in this case are a little dead from the brain, they do not allow an empty loop, so you need to add the op command to execute this run, for example. true or : My tests show that : little faster, although they should be the same , you don’t know why:

 time (i=100000; while ((i--)); do :; done) 

n takes 0.262 seconds, and:

 time (i=100000; while ((i--)); do true; done) 

takes 0.293 seconds. Interesting:

 time (i=100000; while ((i--)); do builtin true; done) 

takes 0.356 seconds.

All measurements average 30 runs.

+4
source

Bash has a built-in no-op, colon (:), which is easier than starting another process to run true .

 #!/bin/bash names=(test test2 test3 test4) for name in "${names[@]}" do : done 

EDIT: William correctly points out that true also an inline shell, so take this answer as another FYI option, and not a better solution than using true.

+3
source

Instead, you can replace anything with "true."

+1
source

You need something in your loop, otherwise bash complains.

+1
source

This error is expected in some versions of bash where the script has been edited on Windows, so the script looks like this:

 #!/bin/bash^M names=(test test2 test3 test4)^M for name in ${names[@]}^M do^M printf "%s " $name^M done^M printf "\n"^M 

where ^ M represents the carriage return character (0x0D). This can be easily seen in vi using the binary option, as in:

 vi -b script.sh 

To remove these carriage return characters, simply use the vi command:

 1,$s/^M// 

(note that the ^ M above is one carriage return character to enter into the sequence of using the Control-V Control-M editor)

0
source

Source: https://habr.com/ru/post/915400/


All Articles