i learned bash very recently, and i’m trying to read arguments for my script. So i wrote this, but i get an error (and vim has highlited in pink the last double parenthesis in the 4th line)
#!/bin/bash for (( i=1; i<=$#; i++ )); do if [[ ${!i:0:1} == "-" ]] && ! [[ ${!i:1} =~ [^a-zA-Z]+ ]]; then for (( j=1; j<=$(($(expr length ${!i})-1)); j++ )); do if [[ ${!i:j:1} == "s" ]]; then k=$((i+1)) if [ -e ${!k} ]; then echo $(realpath ${!k}) fi elif [[ ${!i:j:1} == "o" ]]; then echo "Running script without output!" fi done fi done
I get the following error when i run ./test -so doc1
./tests2: line 13: syntax error near unexpected token `newline' ./tests2: line 13: ` done'
Can anyone help me understand what’s wrong with my script?
Advertisement
Answer
It actually looks like you’ve encountered a bug in bash itself!
Bash fails to handle $(command substitution)
when used inside $((arithmetic expansion))
inside arithmetic for loops:
$ for (( ; ; $(( $(echo 1) )) )); do echo "running"; break; done bash: syntax error near unexpected token `newline'
It’s not just an issue with the extra ))
: bash handles that nesting just fine:
$ for (( ; ; $(( 1 )) )); do echo "running"; break; done running
And it works just fine with deprecated backticks instead of $(..)
$ for (( ; ; $(( `echo 1` )) )); do echo "running"; break; done running
It’s also fine within ((arithmetic commands))
in general, it’s just arithmetic for loops that are affected:
$ while (( $(( $(echo 1) )) )); do echo "running"; break; done running
So yes, congrats, it appears to be a bash bug! I don’t know whether this is a known issue, but for now you can rewrite it as suggested in one of the other posts, or preferably use getopts
.