Skip to content
Advertisement

Error in code for parsing arguments

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.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement