0

I want to print two iterators named i and j of nested for loops whenever they are not equal. The error message:

syntax error near unexpected token `then'

#!/bin/bash
read n
array=()
for i in `seq 1 $n`
do
    read num
    array+=$num
done

count=0
count2=0
countmax=0
for i in `seq 1 $n`; do
    for j in `seq 1 $n`; do
        if [ $i -ne $j ]; then
            echo $i $j
        fi
    done
done

What have I done wrong?

4
  • 1
    works for me, though of course n should be set, $(...) is nicer than backticks and it might be prudent to quote the variables.
    – ilkkachu
    Commented Dec 20, 2017 at 22:11
  • 2
    One potential reason for that error would be a non-breaking space or such instead of normal space after the if. That would make it a different word, not recognized as the if keyword. And then then would be misplaced. (it would be if_[, with _ representing the nbsp)
    – ilkkachu
    Commented Dec 20, 2017 at 22:14
  • Does it work if you copy the code from this page and run it? Commented Dec 20, 2017 at 22:21
  • array+=$num probably doesn't do what you want, you may want array+=($num) instead
    – ilkkachu
    Commented Dec 20, 2017 at 23:16

2 Answers 2

1

What have I done wrong?

In no particular order,

  • You didn't have #!/bin/bash or equivalent as the first line.
  • You don't seem to have posted the actual script that's failing. (What you have here is syntactically correct.)
  • You haven't double-quoted your variables, "$n" instead of $n.
  • You're using obsolete backticks for evaluation instead of $( ...).
  • You haven't tested your code in https://shellcheck.net/
  • You haven't indented your code blocks to make them easier to read.
  • If you are adding elements to an array, use array+=($num). What you have in your code is string concatenation to the last element.
  • In the (new) first block you assign to elements (0 .. n-1) but you later use elements (1 .. n).
  • In the (new) second block you are comparing the indices for inequality rather than the array elements. Did you mean to compare "${array[$i]}" -ne "${array[$j]}" (or, for the (( ... )) construct, array[i] != array[j])?

(I should probably point out that some of these are good practice rather then essential coding rules.)

Here is your code with my suggestions applied:

#!/bin/bash
read -p 'Number of elements: ' n

array=(0)    # We don't use element zero
for i in $(seq "$n")
do
    read -p 'Element: ' num
    array+=($num)
done

for i in $(seq "$n")
do
    for j in $(seq "$n")
    do
        # Compare the array elements rather than the indices
        # Is this what you intended?
        if (( array[i] != array[j] ))
        then
            echo "${array[$i]} ${array[$j]}"
        fi
    done
done
5
  • Maybe slightly better (because easier to read): if (( array[i] != array[j] )) Commented Dec 21, 2017 at 8:54
  • @user1934428 ah yes. Good call. I'd switched from [ ... ] to [[ ... ]] and forgot that variables can be handled even better with (( ... )). Commented Dec 21, 2017 at 9:24
  • @roaima Backticks are not obsolete (or even deprecated) At best, their usage is not recommended.
    – fpmurphy
    Commented Dec 21, 2017 at 9:56
  • @fpmurphy1 I have to disagree with you on that point. See unix.stackexchange.com/q/126927/100397 and mywiki.wooledge.org/BashFAQ/082 and the POSIX statement about $(...) being preferred at pubs.opengroup.org/onlinepubs/9699919799/xrat/… Commented Dec 21, 2017 at 14:55
  • @roaima. Good to see that you went to the ONLY authoritative source on the issue, i.e. POSIX. Please explain how the term you used, i..e "obsolete" is equivalent to the term POSIX uses, i.e. "preferred". BTW, neither of the other two sources you quote are authoritative.
    – fpmurphy
    Commented Dec 22, 2017 at 0:52
0

I would also eliminate the use of seq by using for loops:

#!/bin/bash

read -p 'Number of elements: ' n

array=(0)
for (( i = 1; i <= n; i++ ))
do
    read -p 'Element: ' num
    array+=("$num")
done

for (( i = 1; i <= n; i++ ))
do
    for (( j = 1; j <= n; j++ ))
    do
        (( array[i] != array[j] )) && echo "${array[i]} ${array[j]}"
    done
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .