Bash - How to word if then statement - shell

I'm attempting to append to a file this pseudo code:
if [ `expr $MOD % 5` -eq 0 ]; then.
I did it on shell as:
echo if [ `expr $MOD % 5` -eq 0 ]; then
But it gives me a syntax error near unexpected token 'then'. I can't figure out where I'm going wrong.

Use single quotes:
$ echo 'if [ `expr $MOD % 5` -eq 0 ]; then'
if [ `expr $MOD % 5` -eq 0 ]; then

If I am reading this right, you are trying to append this actual text to a file?
if [ `expr $MOD % 5` -eq 0 ]; then
Then the issue is your command structure. You used this:
echo if [ `expr $MOD % 5` -eq 0 ]; then
This is actually two commands as far as the shell is concerned, due to the semicolon. So it is the same as:
echo if [ `expr $MOD % 5` -eq 0 ]
then
Since then is not normally a valid command, and this is outside the context of a shell conditional (for instance if), the shell doesn't know what to do with it.
What you need to do is quote the entire thing as a string and pass that to echo.
echo 'if [ `expr $MOD % 5` -eq 0 ]; then'
Using single quote (') rather than double quote (") is important. If you use double quote, then the bit in backticks (expr $MOD % 5) would be evaluated instead of passed to the file as-is.

Related

Shell script error : line 170: [: missing ']'

i have the error named in the tittle in shell scripts when i execute this:
if [ $[ $op1 % $op2 ] == 0 ] and [ $res -ne 0 ]
then
resp
else
divi
fi
thanks.
Your first line violates several shell syntax rules.
if [ $[ $op1 % $op2 ] == 0 ] and [ $res -ne 0 ]
and has no meaning in a shell. Just like in C the correct syntax is &&.
And math expressions use $(( ... )).
So you probably meant:
if [ $(( $op1 % $op2 )) == 0 ] && [ "$res" -ne 0 ]
I also added quoting to $res as otherwise expansion takes place. E.g. if $res equals *, it would not compare * to zero but it would expand *, replacing it with the first filename in the current directory and this could cause the test to be true despite $res being *. To prevent this, you must quote $res. You don't need quoting for $op1 and $op2 as in math expression no shell expansion is performed.

Shell Script command not found error

Below my script for up to n prime numbers. When I run it, it always shows an error that command not found in line 12 and 18 both. What am I doing wrong?
clear
echo"enter the number upto which you want prime numbers : "
read n
for((i=1;i<=n;i++))
do
flag=0
for((j=2;j<i;j++))
do
if [expr $i % $j-eq 0]
then
flag=1
fi
done
if [$flag-eq 0]
then
echo $i
fi
done
As pointed out in comments, you must use spaces around [ and ], as well as the comparison operators. Even more safe when using [ and ] is quoting your variables to avoid word splitting (not actually required in this specific case, though).
Additionally, you want to compare the output of expr to 0, so you have to use command substitution:
if [ $(expr "$i" % "$j") -eq 0 ]
and
if [ "$flag" -eq 0 ]
Since you're using Bash, you can use the (( )) compound command:
if (( i % j == 0 ))
and
if (( flag == 0 ))
No expr needed, no command substitution, no quoting required, no $ required, and the comparison operators have their "normal", expected meaning.
There are a number of syntax errors other than the brackets of if statement. Kindly go through the piece of code below. I have checked it running on my system.
#!/bin/sh
echo "enter the number upto which you want prime numbers : "
read n
for((i=1;i<=n;i++))
do
flag=0
for((j=2;j<i;j++))
do
if [ `expr $i % $j` -eq 0 ]
then flag=1
fi
done
if [ $flag -eq 0 ]
then echo $i
fi
done

Arithmetic syntax error with shell script

I am trying to call the function "warn" if the calculation is TRUE. I am still not quite comfortable with the syntax, would like some tips on how to fix the last line.
if [ "$noproc" -gt 0 ]; then
echo "WARNING: NoProc at $noproc for $process processes." >> $log
elif [ "$max" -ge 11 ]; then
[ $(($max - $total)) -lt 6 && [ $idle -le $(($max \* 0.25 | bc -l)) ] ] | warn $total $process $max $idle
The error I get: line 97: [: missing ` ] '
If your tagging for this question is correct and you're genuinely using bash (which is to say that your script starts with #!/bin/bash, or if not started via a shebang you use bash yourscript rather than sh yourscript), you might as well take advantage of it.
# extended bash math syntax
if (( (max - total) < 6 )) && (( idle <= (max / 4) )); then
warn "$total" "$process" "$max" "$idle"
fi
If, for whatever reason, you don't want to use (( )), you can still use [[ ]], which gives you a test context with its own extended syntax:
# extended bash test syntax
if [[ $((max - total)) -lt 6 && $idle -le $(bc -l <<<"$max*0.25") ]]; then
warn "$total" "$process" "$max" "$idle"
fi
...whereas if you want to be compatible with POSIX sh, you need to end the test before you can put in a shell-level logical-AND operator.
# corrected POSIX-compliant test syntax
if [ "$((max - total))" -lt 6 ] && [ "$idle" -le "$(bc -l <<<"$max*0.25")" ]; then
warn "$total" "$process" "$max" "$idle"
fi
To understand why, let's look at how your original command would parse, if you changed the (utterly incorrect) | symbol to && instead:
# Equivalent (longer form) of the original code, with pipe corrected to logical-AND
if [ $(($max - $total)) -lt 6; then
if [ $idle -le $(($max \* 0.25 | bc -l)) ] ]; then
warn $total $process $max $idle
fi
fi
Note that this is running, as a single command, [ $(($max - $total)) -lt 6.
[ is not special shell syntax -- it's just a command. In older shells it was actually /usr/bin/[; today, there's also a [ builtin as well, but other than being faster to execute, it behaves exactly the same way as it would have were it executing the old, external command.
That [ command expects to be passed a ] as its last argument, since there's no ] after the -lt 6, you get a syntax error and it exits.
Similarly, your code would then (if the first command succeeded) run [ $idle -le $(($max \* 0.25 | bc -l)) ] ]. Here, you have a [ command passed two ]s on the end; it simply doesn't know what to do with the second one.
You can't nest [ invocations. Even if you could, a && (b) === a && b in logic.
You can't use commands in arithmetic expansions.
Bash's [[ is safer than [.
Use More Quotes™.
Result:
[[ "$(($max - $total))" -lt 6 ]] && [[ "$idle" -le "$(bc -l <<< "$max * 0.25")" ]] | warn "$total $process $max $idle"

Integer comparison in bash

I need to implement something like:
if [ $i -ne $hosts_count - 1] ; then
cmd="$cmd;"
fi
But I get
./installer.sh: line 124: [: missing
`]'
What I am doing wrong?
The command [ can't handle arithmetics inside its test. Change it to:
if [ $i -ne $((hosts_count-1)) ]; then
Edit: what #cebewee wrote is also true; you must put a space in front of the closing ]. But, just doing that will result in yet another error: extra argument '-'
The ] must be a separate argument to [.
You're assuming you can do math in [.
if [ $i -ne $(($hosts_count - 1)) ] ; then
In bash, you can avoid both [ ] and [[ ]] by using (( )) for purely arithmetic conditions:
if (( i != hosts_count - 1 )); then
cmd="$cmd"
fi
The closing ] needs to be preceded by a space, i.e. write
if [ $i -ne $hosts_count - 1 ] ; then
cmd="$cmd;"
fi

bash shell script syntax error [duplicate]

This question already has answers here:
Why should there be spaces around '[' and ']' in Bash?
(5 answers)
Closed 6 years ago.
I wrote a function in bash script. However, it's complaining about syntax. I really can't see what is it..... the error message is [: missing `]'
addem() {
if [ $# -eq 0] || [ $# -gt 2 ]
then
echo -1
elif [ $# -eq 1 ]
then
echo $[ $1 + $1 ]
else
echo $[ $1 + $2 ]
fi
}
You need a space before the first ]. That is:
change:
if [ $# -eq 0] || [ $# -gt 2 ]
to:
if [ $# -eq 0 ] || [ $# -gt 2 ]
Try:
if [ $# -eq 0 ] || [ $# -gt 2 ]
(There was no space between 0 and ].)
indyK1ng: The "#" is not treated as a comment, since the "$" escapes the next character. The "$#" is an internal variable representing the number of positional parameters that exist at the current context. This can be thought of as the number of command line arguments to the shell script, but that array can be reset using the "set -- [args]" built in.
Joakim Elofsson: The overall structure of the if statement is correct, the ";" is only required before the "then" and before the "fi" if those are not listed on a separate line.
The problem is the space between the "0" and the bracket. Bash requires that brackets used to delimit conditional expressions be set off with at least a single space from the expression.
if [ $# -eq 0] || [ $# -gt 2 ] # Wrong
if [ $# -eq 0 ] || [ $# -gt 2 ] # Correct
On an additional note, the two conditional expressions can be combined. The operator association will ensure that everything works out.
if [ $# -eq 0 -a $# -gt 2 ] # Even Better
I tend to prefer the expanded features offered with double brackets for expression evaluation. Note that the combination of the two evaluations is done with a different operator. I find this to be more readable.
if [[ $# -eq 0 || $# -gt 2 ]] # My preference
Later in the script, the use of single brackets for integer addition is not recommended. The single brackets are evaluating an expression to a boolean. Double parens are used for integer math.
echo $[ $1 + $1 ] # Evaluation of an expression
echo $(( $1 + $1 )) # Integer math
Bash is sensitive to spaces. In your first line, replace if [ Y -eq X] with [ Y -eq X ] (space before the "]")
I would use extended test constructs (BASH) as demonstrated bellow. I think it would reduce the no of characters and increase readability (at least for programmers). :-)
addem() {
if (( $# == 0 || $# > 2 ))
then
echo -1
elif (( $# == 1 ))
then
echo (( $1 + $1 ))
else
echo (( $1 + $2 ))
fi
}
You should avoid brackets and use test instead:
if test $# -eq 0 || test $# -gt 2
then
echo -1
elif test $# -eq 1
then
echo $(( $1 + $1 ))
else
echo $(( $1 + $2 ))
fi
Getting a better shell style will make you much better. :)

Resources