I wait program finish and print nothing; but this intro in loop:
while [ 0 > 0 ]; do echo 1; done
logically 0 no't is > to 0...
why get loop?
How I can get nothing by screen? and program finish fine?
After of my progam "nothing to do":
while [ 0 > 0 ]; do echo 1; done
I like in one line:
q = 0; while [ q < 9 ]; q ++; do echo q; done
it´s possible in one line?
Thanks
q = 0; while [ q < 9 ]; q ++; do echo q; done
Just 5 errors in one line.
q=0 may not have white space around the assignment operator
q ++ has to be in double round parens
q < 9 has to be -lt (less than)
in single brackets [ $q -lt 9 ] q needs to be $q
the do should follow the while
Possible solution:
q=0; while [[ q -lt 3 ]]; do ((q++)); echo $q; done
1
2
3
echoing values can be done with
echo {1..9}
too, but is not flexible, so you can't use variable expansion inside, like echo {1..$n}. The canonical way of doing initialization, increment and threshold check, is a for loop:
for (( q=1; q < 4; ++q)); do echo $q ; done
There is the external program seq, which is not so much recommended, for that reason:
seq 1 3
First question:
while [ 0 > 0 ]; do echo 1; done
Look for a file 0 where you used file redirection (instead of -gt), like in echo foo > 0.file.
Instead of
while [ 0 -gt 0 ]; do echo 1; done
because it does nothing. It doesn't wait for anything. Either your program is sequential, then it is finished at that point anyhow. Or there is a program/command in the background running, which doesn't care about this anti loop anyhow.
For your second question, use
for (( expr1 ; expr2 ; expr3 )) ; do list ; done
Also refer to man bash
Related
I've written the following minimal example to demonstrate
The following does NOT work:
#! /bin/bash
n=1 m=2
while (( n < m ))
echo "$n $m"
(( n=n+1 ))
do
continue
done
The following DOES work:
#! /bin/bash
n=1 m=2
while true
echo "$n $m"
(( n=n+1 ))
do
if (( n < m ))
then
continue
else
break
fi
done
I understand why the second form works. I do not understand why the first form doesn't work.
I wrote these scripts thinking they would be equivalent. (Produce the same output.) However the first loops infinity! Why does this happen?
First, a quick look at the documentation:
$ help while
while: while COMMANDS; do COMMANDS; done
Expand and execute COMMANDS as long as the final command in the
`while' COMMANDS has an exit status of zero.
Note the exact text: the final command in the while COMMANDS is the one whose exit status counts. We'll return to that later.
In your original code:
while (( n < m ))
echo "$n $m"
(( n=n+1 ))
do
continue
done
...you aren't checking whether (( n < m )) is true as your condition; instead, you're checking whether (( n = n + 1 )) is true.
This is true because everything before the do is composed to form the condition that determines whether to continue running the loop, and the exit status of a series of commands separated by newlines or ;s is the exit status of the last command in that series. The only case where (( n = n + 1 )) would not be true (assuming no contents that can't be coerced to an integer or otherwise cause an error) is if the initial value were below 0, and thus the result were 0 or less.
If you really want all those commands to be inside your condition, you could instead write:
while (( n < m )) && echo "$n $m" && (( n = n + 1 )); do :; done
...though of course that has somewhat different behavior (not 'echo'ing if the comparison has failed).
Consider instead:
while (( n < m )); do
echo "$n $m"
(( n++ ))
done
I am trying to write a bash script that accepts a number from the keyboard, and then prints a set of integers from 0 to the number entered. I can't figure out how to do it at all.
This is my code:
while [ 1 ]
do
echo -n "Enter a color: "
read user_answer
for (( $user_answer = $user_answer; $user_answer>0; $user_answer--))
echo $user_answer
fi
done
exit
The error I'm recieving is:
number_loop: line 10: syntax error near unexpected token echo'
number_loop: line 10: echo $user_answer'
Assign a separate variable in order to use increment/decrement operators. $user_answer=$user_answer will always be true and it will throw an error when trying to use decrement. Try the following :
#!/bin/bash
while [ 1 ]
do
echo -n "Enter a color: "
read user_answer
for (( i=$user_answer; i>0; i-- ))
do
echo $i
done
done
exit
You missed the do statement between your for and the echo.
bash has many options to write numbers. What you seem to be trying to do is easiest done with seq:
seq $user_answer -1 0
If you want to use your loop, you have to insert a ; do and replace the fi with done, and replace several $user_answer:
for (( i = $user_answer; i>0; i--)); do
echo $i
done
(btw: I assumed that you wanted to write the numbers in reverse order, as you are going backwards in your loop. Forwards is even easier with seq:
seq 0 $user_input
)
This is where a c-style loop works particularly well:
#!/bin/bash
for ((i = 1; i <= $1; i++)); do
printf "%s\n" "$i"
done
exit 0
Example
$ bash simplefor.sh 10
1
2
3
4
5
6
7
8
9
10
Note: <= is used as the for loop test so it 10 it iterates 1-10 instead of 0-9.
In your particular case, iterating from $user_answer you would want:
for (( i = $user_answer; i > 0; i--)); do
echo $i
done
The for loop is a bash internal command, so it doesn't fork a new process.
The seq command has a nice, one-line syntax.
To get the best of the twos, you can use the { .. } syntax:
eval echo {1..$answer}
I have a zsh script that should generate a bunch of Z-matrix files, but it exits the while loops after one iteration. N and M never increase
#!/bin/zsh
n=0.5
m=0.5
a=60.0
i=1
while [[ $n -le 1.5 ]];do
while [[ $m -le 1.5 ]];do
while [[ $a -le 160 ]];do
echo $i
echo "o" > H2O.$i.Z
eval echo "h 1" $n >> H2O.$i.Z
eval echo "h 1" $m "2" $a >> H2O.$i.Z
let i=$i+1
let a=$a+5.0
done
let m=$m+0.05
done
let n=$n+0.05
done
I'm new to zsh; is my syntax wrong?
The -le operator operates on integers. For floating point, use the built-in arithmetic.
I also believe you might actually want to re-initialize the values for m and a in the inner loops. Then the bug is that you only initialized them once at the beginning and the inner loop conditions on the second iteration were false.
You might use a for((;;)) loop to write this more compact:
#!/usr/local/bin/zsh
i=1
for ((n=0.5; n <= 1.5; n+=0.05)); do
for ((m=0.5; m <= 1.5; m+=0.05)); do
for ((a=60.0; a <= 160; a+=5.0)); do
echo $i $a $m $n
let i=$i+1
done
done
done
Note also that it is unwise to use floating point numbers as loop counts. Did you know that ten times 0.1 is hardly ever one? This might explain why you lose or gain an extra iteration.
Instead, you should iterate using an integer number N and compute the required floats as 0.5 + N * 0.05, for example.
The -le operator only supports integer comparisons. For floating-point, you need to use the ((...)) command. Also, you don't need eval, and you can combine the three echos into one command so you only have to redirect once.
while (( n < 1.5 )); do
while (( m < 1.5 )); do
while (( a <= 160 )); do
echo $i
{ echo "o"; echo "h 1" $n; echo "h 1" $m "2" $a; } > H20.$i.Z
((i+=1))
((a+=5.0))
done
((m+=0.05))
done
((n+=0.5))
done
How to break out of infinite while loop in a shell script?
I want to implement the following PHP code in shell script(s):
$i=1;
while( 1 ) {
if ( $i == 1 ) continue;
if ( $i > 9 ) break;
$i++;
}
break works in shell scripts as well, but it's better to check the condition in the while clause than inside the loop, as Zsolt suggested. Assuming you've got some more complicated logic in the loop before checking the condition (that is, what you really want is a do..while loop) you can do the following:
i=1
while true
do
if [ "$i" -eq 1 ]
then
continue
fi
# Other stuff which might even modify $i
if [ $i -gt 9 ]
then
let i+=1
break
fi
done
If you really just want to repeat something $count times, there's a much easier way:
for index in $(seq 1 $count)
do
# Stuff
done
i=1
while [ $i -gt 9 ] ; do
# do something here
i=$(($i+1))
done
Is one of the ways you can do it.
HTH
I am building a movie database and I need to find a median for ratings.
I'm really new to bash (it's my first assignment).
I wrote:
let evencheck=$"(($Amount_of_movies-$Amount_of_0_movies)%2)"
if [ $evencheck==0 ]
then
let median="(($Amount_of_movies-$Amount_of_0_movies)/2)"
else
let median="(($Amount_of_movies-$Amount_of_0_movies)/2)+1"
fi
When $amount_of_movies = 6 and $amount_of_0_movies = 1. I would expect median to be 3. but it's 2. Why is that?
#!/bin/bash
if (( $# != 1 )) ; then
echo "syntax: `basename $0` number"
exit 255
else
_value=$(expr $1 % 2)
(( $_value == 0 )) && exit 1 || exit 0
fi
try this:
let evencheck="(($Amount_of_movies-$Amount_of_0_movies)%2)"
if [ $evencheck -eq 0 ]
then
let median="(($Amount_of_movies-$Amount_of_0_movies)/2)"
else
let median="(($Amount_of_movies-$Amount_of_0_movies)/2)+1"
fi
Removing the $, and then testing for numeric equality.
try this in your if test:
[ "$evencheck" == 0 ]
Does median have some sort of default value? The way I see it, it's not even going inside the if.
(6-1) % 2
5 % 2
1, not 0
Your code doesn't parse. To evaluate expressions in Bash, you say
let evencheck="$((($Amount_of_movies-$Amount_of_0_movies)%2))"
That is, evaluate arithmetics like so: $(( ... ))
That said, your problem is in the conditional. See man test.
if [ $evencheck = 0 ]; then
You have to wrap the equality sign with whitespace on both sides. Use a single equality sign.
The outermost parentheses and none of the quotes are necessary in what you've got (they may be in other circumstances). Also, in a let statement you can omit the dollar sign from variable names.
let evencheck=(Amount_of_movies-Amount_of_0_movies)%2
if [ $evencheck == 0 ]
then
let median=(Amount_of_movies-Amount_of_0_movies)/2
else
let median=(Amount_of_movies-Amount_of_0_movies)/2+1
fi
If you use the (()) form instead of let, you can uses spaces to make your formulas more readable. You can also use them in if statements:
(( evencheck = ( Amount_of_movies - Amount_of_0_movies ) % 2 ))
if (( evencheck == 0 ))
then
(( median = ( Amount_of_movies - Amount_of_0_movies ) / 2 ))
else
(( median = ( Amount_of_movies - Amount_of_0_movies ) / 2 + 1 ))
fi