-2

I am trying to write a for loop in Bash shell. This is what I came up with:

for i in {0..20..5}
do
  echo "Number: $i"
done

However the output is:

Number: {0..20..5}

I also tried this code:

N=10
for i in 1 2 3 4 5 .. $N
  do
     echo "Welcome $i times"
 done

But in this case too, the output is:

Welcome 1 times
Welcome 2 times
Welcome 3 times
Welcome 4 times
Welcome 5 times
Welcome .. times
Welcome 10 times

I want to write a for loop where I can take the limits as well as the increment or decrement values.

This is the full script:

#! usr/bin/bash

N=10
for i in 1 2 3 4 5 .. $N
  do
     echo "Welcome $i times"
 done

for i in {0..20..5}
do
  echo "Number: $i"
done
Shourya Shikhar
  • 1,342
  • 1
  • 11
  • 29
  • Sure you're using bash for the first one? – Shawn Oct 24 '21 at 11:24
  • Yes. The shell I'm using is bash. I'm adding the full script for your reference in the original question @Shawn – Shourya Shikhar Oct 24 '21 at 11:50
  • 2
    bash has `{start..end}` but not `{start..end..increment}`. Also, since [brace expansion occurs _before_ variable substitution](https://www.gnu.org/software/bash/manual/bash.html#Shell-Expansions), you can't put variables in the `{start..end}` unless you use `eval`. You can use a C-style for loop -- see [3.2.5.1 Looping Constructs](https://www.gnu.org/software/bash/manual/bash.html#Looping-Constructs) in the manual – glenn jackman Oct 24 '21 at 14:08
  • @glennjackman bash certainly does have `{start..end..increment}`. That OP is getting that literally instead of a series of numbers does tell me they're using sh or another shell that doesn't support brace expansion despite the shebang. – Shawn Oct 24 '21 at 18:08
  • @ShouryaShikhar And how are you running your script? – Shawn Oct 24 '21 at 18:10
  • 3
    `{x..y[..incr]}` work fine with bash (see: https://www.gnu.org/software/bash/manual/bash.html#Brace-Expansion)... but with `incr` since version 4 (see: https://wiki.bash-hackers.org/syntax/expansion/brace) – Arnaud Valmary Oct 24 '21 at 18:15
  • @Shawn macOS still ships `bash` 3.2, which doesn't support integer ranges with an explicit step size. – chepner Oct 25 '21 at 00:02
  • That shebang is malformed, though, so it's possible you aren't actually using `bash`. – chepner Oct 25 '21 at 00:03
  • @chepner OP doesn't say they're using a mac (Of course, they don't say they *aren't* using one either...) – Shawn Oct 25 '21 at 01:23
  • @Shawn I'm running the script with `sh scriptname.sh` – Shourya Shikhar Oct 25 '21 at 03:37
  • @CharlesDuffy can you point out what's the error with shebang here? – Shourya Shikhar Oct 25 '21 at 03:52
  • 1
    @ShouryaShikhar, `#! usr/bin/bash` should be `#!/usr/bin/bash`, assuming that the shell really is in `/usr/bin/`. When you leave out the leading `/` it's no longer an absolute path. (BTW, if you don't know `/usr/bin` to be right, use `#!/usr/bin/env bash` so the PATH will be used for the lookup; that's particularly important for MacOS users who may have a newer version of bash in a non-OS-vendor-provided location). – Charles Duffy Oct 25 '21 at 03:52
  • @Shawn Agreed; I was just pointing out a common cause of seemingly valid `bash` code failing to work as expected. – chepner Oct 25 '21 at 12:01

1 Answers1

1

The script seems to be correct.

However as pointed by you in the comments, running the script with sh seems to be the problem here.

In Debian based distros, sh is nowadays linked to "dash" and not "bash". So its most probable that you've been running this script with dash when you execute sh.

To check if sh is linked to "dash", run

ls -la /bin/sh

If the output reads something like this: lrwxrwxrwx 1 root root 4 Oct 18 19:37 /bin/sh -> dash, it's symlinked to "dash".

Now, this should solve the problem.

  1. Make the script executable first.
chmod +x <script_name>.sh
  1. Try running the script now
./<script_name>.sh

This would run the script in bash.

R Das
  • 121
  • 2
  • 1
    Even if `sh` _is_ linked to bash, it still turns off some features (running in `set -o posix` mode) when called under the `sh` name. It's never reliable to treat `sh` and `bash` as synonyms. – Charles Duffy Oct 25 '21 at 12:01
  • Those in this case, brace expansion is not one of the disabled features. – chepner Oct 25 '21 at 12:03
  • 2
    Also, note that it's not good practice to put a `.sh` name on an executable -- extensions should be used for scripts intended to be sourced from another interpreter or loaded as a library, not on commands that select their own interpreter. See [commandname extensions considered harmful](https://www.talisman.org/~erlkonig/documents/commandname-extensions-considered-harmful/), an essay that has been linked from the [bash IRC channel factoid on the topic](https://wooledge.org/~greybot/meta/.sh) for many years now. – Charles Duffy Oct 25 '21 at 12:03