An error with if statement in shell scripting - bash

I'm trying to write a shell script, but it's giving me a syntax error at the following command:
if [[ -n ${array[$x1]} -a [ expr length "$x1" -gt 2 ] ]]
This is the error message:
./project: line 45: syntax error in conditional expression
./project: line 45: syntax error near `-a'
./project: line 45: ` if [[ -n ${array[$x1]} -a [ expr length "$x1" -gt 2 ] ]]'
What am I doing wrong?

Use && not -a in [[ ]]
Also, expr length won't do what you expect here. The better approach, since you're already using bash extensions, is to use the ${#param} expansion to get the length of $param, and evaluate that within a math context, like so:
if [[ -n ${array[$x1]} ]] && (( ${#x1} > 2 )); then
...
fi

Related

Unary operator expected in shell script

I am not sure why my code below generates this error (standard_in) 1: syntax error -bash: [: -eq: unary operator expected . Can someone please help me figure out the problem here? Thanks!
#!/bin/bash
BAMLINES=4.47264e+09
FQ1LINES=4000000
FQ2LINES=4000000
DEBUG=1
if [ ! -z ${DEBUG} ]; then
echo "${BAMLINES} lines in .bam"
echo "${FQ1LINES} lines in all ${FQ_OUT1} files"
echo "${FQ2LINES} lines in all ${FQ_OUT2} files"
if [ $(echo "scale=2;${FQ1LINES}/${BAMLINES} > 0.40" | bc) -eq 0 ]; then
echo "Warning, FQ1 file contains ${FQ1LINES} lines - less than 40% of the number of reads of .bam file"
fi
if [ $(echo "scale=2;${FQ2LINES}/${BAMLINES} > 0.4" | bc) -eq 0 ]; then
echo "Warning, FQ2 file contains ${FQ2LINES} lines - less than 40% of the number of reads of .bam file"
fi
fi
$ echo "scale=2;($FQ1LINES/$BAMLINES) > 0.40"
scale=2;(4000000/) > 0.40
# ..............^^
You want to use either BAMLINE or BAMLINES but not both.
$ echo "scale=2;($FQ1LINES/$BAMLINES) > 0.40" | bc
(standard_in) 1: parse error
Because of that error, the output of $(echo ... | bc) is empty, and then [ only gets 2 arguments. When [ gets 2 arguments, the first operator is expected to be a unary operator (like -z is) -- -eq is not a unary operator.
You need to quote any variables/command expansions within [...]. In this case you'd get a different but more meaningful error:
$ [ "$(echo "scale=2;${FQ1LINES}/${BAMLINES} > 0.40" | bc)" -eq 0 ]
(standard_in) 1: parse error
bash: [: : integer expression expected
Or use [[...]] and you'll just see the bc error
$ [[ $(echo "scale=2;${FQ1LINES}/${BAMLINES} > 0.40" | bc) -eq 0 ]]
(standard_in) 1: parse error

Or statement in bash with grep [duplicate]

This question already has answers here:
How to do a logical OR operation for integer comparison in shell scripting?
(8 answers)
Closed 3 years ago.
I am writing a bash script that cycles through a list of files and does something either when the file contains a certain word, or the file was created within the last X seconds. The script works fine with only the first requirement
if grep -q $error $f; then
, but I don't know how to include the "or" statement.
I have tried the following ( I am new to bash so I tried things that may not even make sense ).
FILES=logdir/*.out
OLDTIME=86400
CURTIME=$(date +%s)
error='exit'
for f in $FILES
do
FILETIME=$(stat $f -c %Y)
TIMEDIFF=$(expr $CURTIME - $FILETIME)
if [[ grep -q $error $f ]] || [[$OLDTIME -gt $TIMEDIFF ]] ; then
or
if [[ grep -q $error $f || $OLDTIME -gt $TIMEDIFF ]] ; then
gives me
./script.sh: line 12: conditional binary operator expected
./script.sh: line 12: syntax error near `-q'
and
if [ grep -q $error $f ] || [ $OLDTIME -gt $TIMEDIFF ] ; then
gives me
./script.sh: line 12: [: too many arguments
./script.sh: line 12: [: 1: unary operator expected
How can I have both conditions in the if statement?
It's easier than you think :-)
if /bin/true || /bin/false; then echo hi; fi
prints hi
if /bin/false || /bin/false; then echo hi; fi
prints nothing.
In other words, you don't need the [ or [[ operators. Just execute the commands to return their status and use || to "or" them.

Bash does into unexpected recursion when processing expression inside [[

I am trying to understand the logic of Bash algorithm.
When I tried this, it printed "a":
a=a;[ $a == "a" ] && echo $a
So far so good. Then I tried the following and it printed "a" again:
a=a;[[ $a == "a" ]] && echo $a
Now I introduced an error by using arithmetic comparison:
a=abc;[ $a -eq "abc" ] && echo $a
I got an error message that makes sense:
-bash: [: abc: integer expression expected
Then I tried to do this with double bracket and got no error, but "abc":
a=abc;[[ $a -eq "abc" ]] && echo $a
I can sort of explain it (bash is trying to be accomodating), but then I got something that puzzles me. If I do that, I get an error message about recursion:
a=a;[[ $a -eq "a" ]] && echo $a
-bash: [[: a: expression recursion level exceeded (error token is "a")
If I use single brackets, there is no recursion but a reasonable error "integer expression expected":
a=a;[ $a -eq "a" ] && echo $a
-bash: [: abc: integer expression expected
This is weird. What Bash is trying to do in that "recursion" case with double brackets? I am talking about:
a=a;[[ $a -eq "a" ]] && echo $a
-bash: [[: a: expression recursion level exceeded (error token is "a")
It's trying to coerce a into a numeric form. It does this by treating its contents as a variable name to dereference; when the result of this is a loop, you get a "recursion level exceeded" error.
Thus:
a=b
b=10
[[ $a -eq 10 ]]
...is true.

Error in shell script: Integer expression expected [duplicate]

This question already has answers here:
Shell equality operators (=, ==, -eq)
(4 answers)
Closed 4 years ago.
i am studying shell script right now. I started to learn how to work with more complex if statements. What's wrong with this code bellow? I read other similar questions here in stackoverflow, but i couldnt resolve my problem. Now im verifying if the first, second or third argument is null. In the future i pretend to verify based in some regex or something like that.
Thanks!!
The code (line 9):
if [ "$1" -eq "" ] || [ "$2" -eq "" ] || [ "$3" -eq "" ] then ...
line 9: [: : integer expression expected line 9: [: : integer
expression expected line 9: [: : integer expression expected
-eq performs an arithmetic comparison between two numbers. Use = for string comparisons. Or better yet, use [[ and ==.
[[ $1 == "" ]]
[ "$1" = "" ]
You can also use -z and -n to directly test whether a value is empty/non-empty.
[[ -n $value ]] # [[ $value != "" ]]
[[ -z $value ]] # [[ $value == "" ]]
use [[ and ]] for the more modern / complex operators. This is a bashism, so beware.

Fix if condition in shell script

I have these if conditions, but it has compile errors. How can I fix it?
if [ $DEVICE_ID == "" ]; then
I get error:
line 63: [: ==: unary operator expected
if [ 'ls -l Mytest*.log | wc -l' -eq 1 ]; then
i get error:
line 68: [: ls -l Kernel*.log | wc -l: integer expression expected
Quote the variable:
if [ "$DEVICE_ID" == "" ]; then
But it would be better to do:
if [ -z "$DEVICE_ID" ];
The second error is that you need to use backquotes:
if [ $(ls -l Mytest*.log | wc -l) -eq 1 ]; then
If you're using bash, use double brackets for conditional expressions: they are smarter about unquoted variables
if [[ $DEVICE_ID = "" ]]; then ...
would work (note: = instead of == for plain string equality instead of pattern matching)
For presence of files use an array
shopt -s nullglob
files=( *.log )
if (( ${#files[#]} > 0 )); the. Echo "there are log files"; fi

Resources