0

From the below script I am assigning the command substitution for the array variables. When I execute the script, the script is throwing error as

myscript.sh: 22: scr4.sh: Syntax error: "(" unexpected

ie while executing the command suite=( echo $Suites ).

I took this script from Advanced Bash scripting Guide pdf. When I run this command by command in CLI, there is no issue. What is the solution for this?

#!/bin/bash

Suites="Clubs
Diamonds
Hearts
Spades"

Denominations="2
3
4
5
6
7
8
9
10
Jack
Queen
King
Ace"

suite=( `echo $Suites` )

denomination=( `echo $Denominations` )

num_suites=${#suite[*]}

num_denominations=${#denomination[*]}

echo -n "${denomination[$((RANDOM%num_denominations))]} of "

echo ${suite[$((RANDOM%num_suites))]}

exit 0
Green
  • 577
  • 3
  • 10
  • 28
  • 1
    `myscript.sh: 22: scr4.sh:` - where is `myscript.sh`? Where is `scr4.sh`? Are you sure there is `#!/bin/bash` as the first line in each of these files? – KamilCuk Apr 06 '20 at 14:02
  • 4
    If you got that directly from a guide... I would find a better guide. – Shawn Apr 06 '20 at 14:04
  • Are you running this with `sh myscript.sh` per chance? – Benjamin W. Apr 06 '20 at 14:18
  • Combining `echo` and backticks this way is almost always a mistake, since they mostly cancel each other out -- just use the variable directly. Except that relying on word-splitting on an unquoted variable is also subject to weird parsing effects, so that should be avoided as well. It's better to define arrays *as arrays* than to try to fill them from strings via dubious parsing methods. Also: use [shellcheck.net](https://www.shellcheck.net)! – Gordon Davisson Apr 06 '20 at 16:09

1 Answers1

2

You're probably using the wrong interpreter.

$ bash cards.sh
King of Diamonds
$ sh cards.sh
cards.sh: 22: Syntax error: "(" unexpected

POSIX shell does not support arrays. You define an array on line 22 (suite=( `echo $Suites` )) and another on the next code line, then most of your remaining lines refer to those arrays. $RANDOM is also unavailable in POSIX.

Another note, you don't need those subshells. Here's a cleaned up version of your code:

#!/bin/bash

suit=( Clubs Diamonds Hearts Spades )
denomination=( {2..10} Jack Queen King Ace )

echo -n "${denomination[ $(( RANDOM % ${#denomination[@]} )) ]} of "

echo "${suit[ $(( RANDOM % ${#suit[@]} )) ]}"

exit 0

This doesn't launch any subshells. Instead, it's directly defining the arrays. I used {2..10} (another bashism) as shorthand for listing each number. Rather than storing the lengths in variables, I'm invoking them directly in the modulo math, which I've spaced out to make more legible.

I changed ${variable[*]} to ${variable[@]} as well. This doesn't matter in your particular code, but it's generally better to use @ since it is better at preserving spacing.

I also corrected the spelling of your suite variable to suit. Feel free to revert if that's actually what you desired (perhaps due to a spoken language difference). It of course doesn't really matter as long as you're consistent; bash doesn't know English

Adam Katz
  • 14,455
  • 5
  • 68
  • 83