One line if statement in bash - bash

I've never programed in bash... yet I'm trying to solve a problem for an anchievement in a game (codingame.com)
I have the following code:
for (( i=0; i<N-1; i++ )); do
tmp=$(( sorted_array[i+1] - sorted_array[i] ));
if [ $tmp < $result ]; then result=$tmp fi
done
And this error:
/tmp/Answer.sh: line 42: syntax error near unexpected token `done'at Answer.sh. on line 42
/tmp/Answer.sh: line 42: `done' at Answer.sh. on line 42
I want to compare adjacent values of my array and store the minimun diference between them... but I cant figure how to do an If statement in bash

Each command must be properly terminated, either by a newline or a semi-colon. In this case, you need to separate the assignment of result from the keyword fi. Try adding a semi-colon;
for (( i=0; i<N-1; i++ )); do
tmp=$(( sorted_array[i+1] - sorted_array[i] ))
if [ "$tmp" -lt "$result" ]; then result=$tmp; fi
done
Also, you need to use lt rather than <, since < is a redirection operator. (Unless you intend to run a command named $tmp with input from a file named by the variable $result)

You are missing a semicolon and need to use -lt instead of <, as others pointed out.
An alternative to the if statement would be to use the logical and operator &&:
for (( i=0; i<N-1; i++ )); do
tmp=$(( sorted_array[i+1] - sorted_array[i] ))
[ $tmp -lt $result ] && result=$tmp
done

Your if needs to be followed by a fi command, but you don't have any such command. You have a fi in your code, but it's in the middle of another command, so it no more completes the if then the fi in echo fi would. If you're going to merge lines together, you need to use a semi-colon to separate the commands.
So to collapse
for (( i=0; i<N-1; i++ ))
do
tmp=$(( sorted_array[i+1] - sorted_array[i] ))
if [ $tmp -lt $result ]
then
result=$tmp
fi
done
you'd use
for (( i=0; i<N-1; i++ )); do
tmp=$(( sorted_array[i+1] - sorted_array[i] ))
if [ $tmp -lt $result ]; then result=$tmp; fi
done
Exception: do and then can be followed by a command, so you don't need a semi-colon after them when you merge in the next line.
Notice how you don't need to terminate your commands with ;? ; is only needed between commands.
Inside of a test ([]), -lt is used to compare numbers.

Related

What is the difference between -lt and < in shell?

I'm studying shell scripting and don't understand the difference between -eq and ==, -lt and <, -gt and >, so on.
I'm trying to write a while loop printing out from 0 to 9
num=0
while [ $num -lt 10 ]; do
echo "$num"
((num++))
done
This code works but when I change -lt to <, it says No such file or directory.
num=0
while [ $num < 10 ]; do
echo "$num"
((num++))
done
What is the issue with < here? Do I always have to go for -lt in while loops? Is there a general way to do while loops? Appreciate if you can help.
Shell scripting has been always different when it comes to syntax.
so when you say -lt it means less than (<).so when you write your code it works totally fine
while [ $num -lt 10 ]; do
echo "$num"
((num++))
done
But when you use < this in the shell script it is used to read input from file or directory. So here in your case, it will search for the name of the file which is inside the $num variable
In simple words
-lt is Less than which is used for condition checking
< is used for Reading input from the files.
In commandline
< means read input from file
for example
grep "myname" < data.txt
also,
> redirect output to a file
for example ls > lists.txt
when executing $num < 10
it checking for a file named 10
The command [ specifies that -lt should be used to compare two integers. Expecting < to do anything useful is simply wishful.
Coincidentally, the character < is a metacharacter in bash used for input redirection. The error you get is due to the file 10 not existing in your cwd.
You can use '<' with double parentheses (integers) or curly brace (strings)
num=0
while (( $num < 10 )); do
echo "$num"
((num++))
done
and for strings
str="a"
while [[ $str < "aaaaa" ]]; do
echo "$str"
str+="a"
done

Why does math, like "while ($i < $MAX)", give "no such file or directory"?

I wrote a shell script into a file named test.sh, and the code as following:
echo "start"
declare -i i=1
declare -i MAX=99999999;
while ($i < $MAX)
do
# do something
let ++i;
done
echo "done"
The result is:
start
test.sh: line 3: 99999999: No such file or directory
done
I run it on Max os Yosemite 10.10.2 and the terminal is bash.
Where am i wrong?
Okay the problem is with ($i < $MAX) it will not work in bash. In your case it taking < as redirect operator so it is treating < $MAX as you are giving $MAX file redirection to any loop. SO it is treating $MAX as file. That's why the error.
use
[ "$i" -lt "$MAX" ] ### generic POSIX number comparison syntax
or
[[ $i -lt $MAX ]] ### extended (bash/ksh/zsh) number comparison syntax
or
[[ $i < $MAX ]] ### extended string comparison syntax (may give wrong result for numbers)
or
(( i < MAX )) ### extended number comparison syntax

Syntax error near unexpected token `if' in shell scripting

I was trying a sample program, to check the odd and even no's and was getting an error as below,
#!/bin/bash
N=10
for i in 1..N
if [$i/2 == 0]
then
echo "even"
else
echo "Odd"
fi
Error:
./case.sh: line 5: syntax error near unexpected token `if'
./case.sh: line 5: `if [$i/2 == 0]'
EDITED :
#!/bin/bash
N=10
for i in 1..N
do
if(( ($i/2) == 0 ));
then
echo "even"
else
echo "Odd"
fi
done
error :
./case.sh: line 6: ((: (1..N/2) == 0 : syntax error: invalid arithmetic operator (error token is "..N/2) == 0 ")
Odd
Correct working code :
#!/bin/bash
N=3
for (( i=1; i <= N; i++ ));
#for i in 1..N; // This didnt work
do
if [[ $i/2 -eq 0 ]]
#if (( i/2 == 0 )); // This also worked
then
echo "even"
else
echo "Odd"
fi
done
[ ] or [[ ]] needs spaces between its arguments. And in your case you should use [[ ]] or (( )) as [ ] can't handle division along with comparison:
if [[ 'i / 2' -eq 0 ]]; then
if (( (i / 2) == 0 )); then
for i in 1..N; do should also be
for (( i = 1; i <= N; ++i )); do
You probably meant to have a form of brace expansion, but you can't apply a parameter name on it:
{1..10} ## This will work.
{1..N} ## This will not work.
Using eval may fix it but better go for the other form of for loop instead.
Try this :
#!/bin/bash
N=10
for i in $(seq 1 $N); do
if [ `expr $i % 2` -eq 0 ]
then
echo "even"
else
echo "Odd"
fi
done
1..N is not a valid syntax in bash(though I think you might be coming from ruby background), you can use seq.

Loop condition in bash

In bash script, below while loop is supposed to print 1 to 4 number.
But this one is resulting as an infinite loop.
COUNT=1
while [ $COUNT < 5 ];
do
echo $COUNT
COUNT=$(($COUNT+1))
done
Is there any fault in condition or syntax ? (I think so...)
Use -lt instead of <:
COUNT=1; while [ $COUNT -lt 5 ]; do echo $COUNT; COUNT=$(($COUNT+1)); done
1
2
3
4
BASH syntax with [ doesn't recognize >, <, <=, >= etc operators. Check man test.
Even better is to use arithmetic processing in (( and )):
COUNT=1; while (( COUNT < 5 )); do echo $COUNT; ((COUNT++)); done
OR using for loop:
for (( COUNT=1; COUNT<5; COUNT++ )); do echo $COUNT; done

bash/ shell script while statement

I'm new in shell programming ... basically I'm novice at all but I need a simple script to do while loop and execute a php script . I've tried the following :
!/bin/bash
i=0
while[ i < 13 ]
do
php /var/www/html/pos.php &
(( i++ ))
done
but for some reasons the syntax is not good ... I'm getting error line 4: syntax error near unexpected token `do'
You need to have a space between while and the left bracket [, and you need to put the do on a separate line or use a semicolon (both of those are fairly common mistakes when writing loops). Additionally, the left bracket [ is equivalent to man test which supports -lt but not <:
function doStuff() {
local counter=0
while [ $counter -lt 10 ]
do
echo $counter
let counter=$counter+1
done
}
doStuff
OR
function doStuff() {
local counter=0
while [ $counter -lt 10 ] ; do
echo $counter
let counter=$counter+1
done
}
doStuff
!/bin/bash
i=0
while (( i < 13 ))
do
php /var/www/html/pos.php &
(( i++ ))
done
alternatively, you can use a for loop
for((i=1;i<=13;i++))
do
php /var/www/html/pos.php &
done
since the for loop already creates the counter you, you don't have to declare a counter manually.
can't see your code, but it should be like this
while [ $i -ne 3 ]
do
echo "on number $i of 3"
i=`expr $i + 1`
done
I suppose that you want to do something like:
i=0; while (($i<10)); do i=$((i+1)); echo $i; done

Resources