1

I've got two variables and I'm trying to run a for loop from one of them:

a=5  
z="i=0;i<=$a;i++"
x="i=$a;i>=1;i--"
read -p "choose loop:" loop
  case "$loop" in
    plus ) l="$z" ;;
    minus ) l="$x" ;;
  esac

for (($l)) do
#also tried (('$l')) & (("$l"))
  ...
done

When I'm doing this I've got:

syntax error: arithmetic expression requiered
syntax error:'(($l))'

So I tried:

a=5
x="\(\(i=1;i<=$a;i++\)\)"
#also tried "((...))"

for $x do
  ...
done
#also tried "$x" & '$x'

But when I'm doing this i've got:

bash: '"$l"': not a valid identifier.

But I want only one "loop construction" I don't want to copy my code twice.
So what should i do for run my loop and don't have to write my code twice inside the loop?

3 Answers 3

3

You can store the list in a variable using seq:

loop_max=5
read -p "choose loop:" loop
case "$loop" in
  plus) myseq=$(seq 0 "$loop_max");;
  minus) myseq=$(seq "$loop_max" -1 0);;
esac

for i in $myseq; do
  echo "$i"
done

Edit:

You can also set the seq arguments in the case statement and call seq in you for loop:

loop_max=5
read -p "choose loop:" loop
case "$loop" in
  plus) start="0";;
  minus) end="-1 0";;
esac

for i in $(seq $start "$loop_max" $end); do
  echo "$i"
done
Sign up to request clarification or add additional context in comments.

4 Comments

This is very elegant!
Thanks @codeforester. I was thinking of using just one seq command but I found it would have been less readable.
@SLePort Just for knowledge you can post how you do with only seq command ?
@SLePort , first one is good for understand but second one is shortest and even more what i was really excepting for . Thanks you .
2

I don't think for syntax allows what you are trying to do. Instead, do this to keep it more readable:

loop_max=5
read -p "choose loop:" loop
case "$loop" in
   plus) loop_type="ascending"
    ;;
  minus) loop_type="descending"
    ;;
esac

[[ $loop_type == "ascending" ]] && for ((i = 0; i <= $loop_max; i++)); do
  : your code goes here
done

[[ $loop_type == "descending" ]] && for ((i = $loop_max; i > 0; i--)); do
  : your code goes here
done

The case statement is not adding much value. So, you could rewrite the whole thing this way:

loop_max=5
read -p "choose loop:" loop_type
if [[ $loop_type == "plus" ]]; then
  for ((i = 0; i <= $loop_max; i++)); do
    : your code goes here
  done
elif [[ $loop_type == "minus" ]]; then
  for ((i = $loop_max; i > 0; i--)); do
    : your code goes here
  done
else
  printf "Invalid choice.\n"
fi

Comments

0

You can modify your for loop to look like this:

for j in $l 
do
    echo $j; # whatever you need to do here 
done

Hope this will solve your purpose.

2 Comments

Did you test it? It won't iterate the way OP wants it - it will run the loop only once with j set to the value of $l.
@codeforester, I see that you have posted the correct answer. I tried to address his issues with "not a valid identifier" error that he was facing. As is evident from your answer, there are multiple issues with his script.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.