8
x=1
while [ $x -le 50 ]
do
    echo $x
    $x=(($x + 1))
done

I have wrote the above code. What seems to be a easy task in many programming languages is giving this error for me.

solution.sh: line 5: syntax error near unexpected token `('
solution.sh: line 5: `    $x=(($x + 1))'

How to debug errors in bash. Is there any IDE?

9
  • Use bash -x scriptname to debug. Commented Dec 8, 2014 at 11:51
  • 3
    There are 2 mistakes. The line should be x=$(($x + 1)). But easy to use seq instead all script seq 50 Commented Dec 8, 2014 at 11:52
  • 3
    Just so you know, in bash, you can do echo {1..50}. And in $(()) environment, the variables inside are automatically evaluated, which is why you don't need the $ inside it again. Commented Dec 8, 2014 at 11:55
  • 1
    Thanks, @muru I started 10 mins back. thinking of doing it in normal way first. Commented Dec 8, 2014 at 11:57
  • 1
    @WannaBeCoder you are using let and could also just do ((x++)). Also look up the let command. Commented Dec 8, 2014 at 12:01

9 Answers 9

17

A shell is not a (good) programming language, it's (before all) a command line interpreter. Use a counting command if you want to count, not the echo and [ commands in a loop.

For instance, GNU systems have the seq command for that. Alternatives are awk or bc for instance:

seq 50
echo 'for (i=1; i<=50; i++) i' | bc
awk 'BEGIN {for (i=1; i<= 50; i++) print i}'

If you find yourself using a loop in shells, chances are you're going for the wrong approach.

5
  • 3
    The beauty of Shell is that there are commands to do most things that are commonly useful but hard to implement. In this case, seq 50 is the one correct answer to OP's question: THIS is how you print numbers 1-50 in shell. Commented Dec 8, 2014 at 12:17
  • 2
    @SF. If you want shell, seq is hardly the 'right' way. echo {1..50} (or printf) would arguably be the shell way. Commented Dec 8, 2014 at 12:21
  • 2
    Stéphane, I would only argue with you that there are plenty of times to use loops in bash. Looping is a basic programming construct, and is even applicable in shells (though admittedly, it makes more sense to use a foreach loop in most of those cases). Commented Dec 8, 2014 at 12:36
  • 1
    @HalosGhost Perhaps Stephane prefers recursion to iteration. :) Commented Dec 8, 2014 at 12:39
  • @muru, possible though that may be, I remain unconvinced that looping signals wrong-doing in shell. Additionally, I already said I typically prefer a foreach-style loop in most of those cases (which is often not strict iteration). Commented Dec 8, 2014 at 12:41
11

Print numbers from 1-50

printf '%s\n' {1..50}

print numbers from 1-50 with step say 2 (bash 4+):

printf '%s\n' {1..50..2}
1
  • 1
    +1. Using the Bash builtins and avoiding interpreter-level loops makes this substantially faster than many of the other shell solutions, including my own. Commented Sep 15, 2018 at 19:56
9

On line 5: Change $x=(($x + 1)) to x=$(($x + 1)).

Instead of using an entire bash script, you can just use seq 1 50.

If the case were x=$(($x + 2)), you could use seq 1 2 50, where 2 denotes step/increment.

8
  • Shouldn't that be x=$(( x + 1 )) ? No dollar symbol within the double brackets. Commented Dec 8, 2014 at 12:28
  • 1
    @garethTheRed, $((x + 1)) would not work with some old versions of ash based shells, and is currently not clearly specified by POSIX (under discussion there) but would work in most shells nowadays. $(($x + 1)) is clearly specified but $((1-$x)) for instance has issues that $((1-x)) (or x=$((1-($x)))) don't have. x=$((x + 1)) is safe in modern versions of ash based shells even if x doesn't contain a number. Both have security implications in most other shells. Commented Dec 8, 2014 at 12:38
  • 1
    @StéphaneChazelas the question is tagged bash. Does it matter what happens elsewhere? Commented Dec 8, 2014 at 12:40
  • 2
    @muru, to many people, yes, it does. And my comment was not addressed to the OP (and besides is just general information on the benefit of either in the general case). Commented Dec 8, 2014 at 12:46
  • @StéphaneChazelas - Before commenting, I tested x=$(($x + 1)) and it errored for me. I've tried it again and now it works. Aargh! Commented Dec 8, 2014 at 12:48
7

Use Brace-Expansion Ranges

Other answers may address how to debug your script. This answer shows you a simpler (and less error-prone) way to do what you want using Bash's brace-expansion to generate a range instead of an incrementing loop.

For example, to print the numbers 1 through 50 using this notation, you can use the following snippet:

for x in {1..50}; do
    echo $x
done 

This will correctly print each number in sequence, but relies on features of Bash that aren't portable across shells. If you need portability, consider using seq instead.

1
  • Beware that seq is not portable either not being part of the POSIX specified utilities. Commented Dec 8, 2014 at 23:21
3

There is software called BASH debugger and other software will be shellcheck which will give you general errors but not all.

In your script in line 5 use square brackets:

x=$[ $x + 1 ]

Update

Or

x=$(( $x + 1 ))

former one is depricated, better use latter one. Don't use $ before x which comes before = sign

1
  • 3
    Just so you know, even though the TLDP Bash beginner's guide recommends this syntax, it is deprecated. Commented Dec 8, 2014 at 12:10
2

From your other question about rounding decimals, I see that you want to do this only in bash. So apart from the other answers, you can do it this way too.

#!/bin/bash
x=1
while [[ $x -le 50 ]]
do
    echo $x
    x=$(expr $x + 1)
done
2

On systems with the jot command (BSD systems):

jot 50
1
  • This works on macOS (which is a BSD system) Commented Jul 20, 2022 at 22:21
1

Bash like ksh and possibly some other shells natively supports arithmetic loops:

for ((x=1;x<=50;x++)); do
    echo $x
done
0
#!/bin/bash
for i in $(seq 1 50)
do
echo $i
done

edit: sorry for posting my answer without reading the tour guide and thanks Stephen Kitt to edit my answer.

So in this script, I get the output of seq 1 50 with command substitution $() and iterate that output(sequence of numbers from 1 to 50) with for, and print every i in that sequence with echo $i

And just because you try to print the numbers with loop, I implement it with loop. seq 1 50 or echo {1..50} will give those numbers too, without using iteration.

1
  • 2
    Welcome to Unix.SE! Please take a moment to look at the tour, and edit your answer to explain how its specifics (especially compared to the other answers). Also consider how this is different from a plain seq 1 50 (instead of the loop). Commented Mar 23, 2018 at 8:30

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.