1

I had a set of conditionals working perfectly. However, I needed to tweak the algorithm (making it more complicated), which involved nested conditionals in bash.

For instance, here is one such block:

a1=C
a2=P
a3=E
a4=1
a5=7
a6=0
a7=4
a8=T
a9=K
a10=S
letters=$(echo {A..Z} | tr -d ' ')
if [ "$c3" != "$a3" ]
    then
        c3=${letters:$((RANDOM%26+1)):1}
        if [ "$c3" == "$a3" ] && (( $count % $difficulty3 != 0 ))
        then
            c3=${letters:$((RANDOM%26+1)):1}
            if [ "$c3" == "$a3" ] && [ [ "$c1" != "$a1" ] || [ "$c2" != "$a2" ] ]
            then
                c3=${letters:$((RANDOM%26+1)):1}
            fi
        fi
    fi

The innermost if statement essentially checks, if c3 and a3 are equal, to make sure that c1 and a1 are also equal and that c2 and a2 are also equal. If not, it reassigns the variable c3 once more.

My thought is to do an if (true AND ( true OR true)) type logic, but this doesn't seem to work here. I get:

line 367: [: too many arguments

All the c and a variables are a single letter or numerical digit, so strings with spaces as I've seen in related SO posts on this subject are not causing the issue.

When I try doing double brackets instead of single around the whole thing, the script fails to run at all. Parentheses won't work since these aren't arithmetic operations... so I'm scratching my head now. It seems this is the proper way to do nested conditionals... what am I missing?

codeforester
  • 39,467
  • 16
  • 112
  • 140
InterLinked
  • 1,247
  • 2
  • 18
  • 50
  • @Roadowl Basically what I am trying to do is if all the lowered number a and c variables are matching, it's fine, but if *not* (if any of them are NOT equal), then I do the assignment again – InterLinked Jul 22 '19 at 22:58
  • Can you add some initial values to the script so others can run it and see it fails in the way you describe? –  Jul 22 '19 at 23:01
  • @Roadowl That's it, the code runs on its own, except for 1 variable which I added - I see you also meant the comparison variables, I just added those – InterLinked Jul 22 '19 at 23:02
  • Consider using `[[`. See this answer: [Compound if statements with multiple expressions in Bash](https://stackoverflow.com/a/55524251/6862601). – codeforester Jul 22 '19 at 23:36
  • @InterLinked : You never assign something to `difficulty3`. – user1934428 Jul 23 '19 at 06:19
  • @user1934428 I did, I forgot to add that code... – InterLinked Jul 23 '19 at 21:07

1 Answers1

4

Square brackets look like special shell syntax but they're not at all. [ is just another name for test, and the closing ] is merely an argument that's ignored.

You can use curly braces, which are special syntax:

if [ "$c3" == "$a3" ] && { [ "$c1" != "$a1" ] || [ "$c2" != "$a2" ]; }

Parentheses also work. The extra ; isn't needed, but they create an unnecessary sub-shell, so I recommend curly braces:

if [ "$c3" == "$a3" ] && ( [ "$c1" != "$a1" ] || [ "$c2" != "$a2" ] )
John Kugelman
  • 349,597
  • 67
  • 533
  • 578