-1

This Linux program is supposed to print 0 to 4. But I'm unable to find error in this code.

#!/bin/sh

a=0

while [ $a -lt 5 ]
do
    echo $a
    a='expr $a + 1'
done

When I try to run it, it says 'Line 5: [: too many arguments'.

  • 1
    Please give your question a more descriptive title. – phk Oct 17 '16 at 17:55
4

You have use to backtick quotes for command substitution

a=`expr $a + 1`
2

I've provided three examples, first two are with while loops and the third is with an until loop. The first example uses very close syntax to your original, the third is a bit more complex as it uses dynamic settings for counter maximum and an array for iterating though words (space separated arguments) passed one at a time. Now these are simple examples and intended to only answer your direct questions in the scripting language of Bash if you want more advanced examples see the link attached to a script I'm maintaining on GitHub for examples of nested loops among other tech-wizardry.

Example one

#!/usr/bin/env bash
let _counter=0
let _max="5"
while [ "${_counter}" -lt "${_max}" ]; do
    echo "${_counter}"
    let _counter=++
done
unset _counter
unset _max

Running example one example

./example_one.sh
1
2
3
4
5

Example two

#!/usr/bin/env bash
_arr_args=( "${@}" )
let _counter=0
let _max="${#_arr_args[@]}"
while [ "${_counter}" -lt "${_max}" ]; do
    echo "${_arr_args[${_counter}]}"
    let _counter=++
done
unset _counter
unset _max

Running example two example

./example_two.sh "$(seq 1 5)"
## same output as example one

Example three (bonus)

#!/usr/bin/env bash
_arr_args=( "${@}" )
let _counter=0
let _max="${#_arr_args[@]}"
until [ "${_counter}" = "${_max}" ]; do
    echo "${_arr_args[${_counter}]}"
    let _counter=++
done
unset _counter
unset _max

Running example three example

./example_three.sh "$(seq 1 5)"
## same output as example one

Notes for new Bash script writers

  • look up built-in variables/arrays and substitutions rules; it'll save you time, effort, and from unneeded piping to other programs.
  • look up shellcheck it's available in most distributions, and in source form from it's authors, and is integrated into Code Climate with GitHub.
  • as eluded to above here is the link to an example of a script that makes use of both looping types shown above as well as auto code checking. However, the scripts' intention is well beyond the scope of answering the above question so search for "while" & "until" to find the relevant functions that use these calls.
  • bash != sh there are similarities but they're different, personally I find bash to be the better choice because it's less likely to bugger-up if given a sh script where as shell will do odd things with bash syntax.
0

You are assigning the string 'expr $a + 1' to a. That's not likely what you want. Just change single quotes to backticks and it will work:

a=`expr $a + 1`

The above should answer your question. Below is some additional thoughts:

If your /bin/sh implementation is Bash, you could also consider using $(...) instead of backticks. This has several advantages: it avoids typographic confusion between the single quote and the backtick, the $(...) form can be nested, and each nesting is in its own quoting context (so you can do things such as:

variable="$(somecommand -o "$file")"

Here is another implementation:

#/bin/bash

declare -i a=0
while [[ $a -lt 5 ]]; do
   echo $a
   ((a++))
done

Note that sh is not an implementation. So, to answer your question safely, we'd need to know if your intention includes POSIX portability, or if you are interested in a particular implementation such as Bash, dash, tcsh, etc.

  • $(...) is POSIX, it will work in any POSIX shell (so the POSIX sh of any system, most of the time found in /bin), not just bash $((...)) arithmetic expansion is also POSIX. – Stéphane Chazelas Oct 17 '16 at 14:09
  • @ValentinB. $(...) is POSIX but not Bourne. Every system will have a sh where that works but not necessarily in /bin like on Solaris 10 and older where /bin/sh is the Bourne shell (an ancient, non-POSIX shell), and the standard shell is in /usr/xpg4/bin – Stéphane Chazelas Oct 17 '16 at 14:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.