-bash: [: #: binary operator expected - bash

all,
I am checking the error info in a file in the last line, I would like to have a "yes" result if there is an "Error". My shell script is like below:
[ $(tail -1 error.log | grep -E "Error") ] && echo "yes"
then I got the error like above in the title:
-bash: [: #: binary operator expected
The error message in the last line is like below:
[aaa,bbb,ccc, Error.ddd # ]
I think that is because of the the Error message, which has [ # ] format content caused this error. But I do not know how to fix it. Is there any one knows how to process this [ # ] problem. Thanks very much
#csiu, thanks very much for your quick reply.
The trick here is to use double "[" as below:
[[ $(tail -1 error.log | grep -E "Error") ]] && echo "yes"

well since my comment works, might as well post it in the answer section ;)
Use double "[["
[[ $(tail -1 error.log | grep -E "Error") ]] && echo "yes"
Related posts:
How to use double or single bracket, parentheses, curly braces
Meaning of double square brackets in bash

Additionally to #csiu's answer, don't need the test command at all. You can operate based on grep's exit status:
tail -1 error.log | grep -qE "Error" && echo yes
Use -q to silence the output from grep. It's also more efficient because grep will exit immediately once the pattern is found.
Since we only have one line of input, we don't even need grep:
[[ $(tail -1 error.log) == *Error* ]] && echo yes

Related

How can I get the return value and matched line by grep in bash at once?

I am learning bash. I would like to get the return value and matched line by grep at once.
if cat 'file' | grep 'match_word'; then
match_by_grep="$(cat 'file' | grep 'match_word')"
read a b <<< "${match_by_grep}"
fi
In the code above, I used grep twice. I cannot think of how to do it by grep once. I am not sure match_by_grep is always empty even when there is no matched words because cat may output error message.
match_by_grep="$(cat 'file' | grep 'match_word')"
if [[ -n ${match_by_grep} ]]; then
# match_by_grep may be an error message by cat.
# So following a and b may have wrong value.
read a b <<< "${match_by_grep}"
fi
Please tell me how to do it. Thank you very much.
You can avoid the double use of grep by storing the search output in a variable and seeing if it is not empty.
Your version of the script without double grep.
#!/bin/bash
grepOutput="$(grep 'match_word' file)"
if [ ! -z "$grepOutput" ]; then
read a b <<< "${grepOutput}"
fi
An optimization over the above script ( you can remove the temporary variable too)
#!/bin/bash
grepOutput="$(grep 'match_word' file)"
[[ ! -z "$grepOutput" ]] && (read a b <<< "${grepOutput}")
Using double-grep once for checking if-condition and once to parse the search result would be something like:-
#!/bin/bash
if grep -q 'match_word' file; then
grepOutput="$(grep 'match_word' file)"
read a b <<< "${grepOutput}"
fi
When assigning a variable with a string containing a command expansion, the return code is that of the (rightmost) command being expanded.
In other words, you can just use the assignment as the condition:
if grepOutput="$(cat 'file' | grep 'match_word')"
then
echo "There was a match"
read -r a b <<< "${grepOutput}"
(etc)
else
echo "No match"
fi
Is this what you want to achieve?
grep 'match_word' file ; echo $?
$? has a return value of the command run immediately before.
If you would like to keep track of the return value, it will be also useful to have PS1 set up with $?.
Ref: Bash Prompt with Last Exit Code

Bash IF statement

rather noobie question here.. i think. but i cant get this script to work. It is going to be included inside a script that i asked about here a few days ago (BASH output column formatting). basically i want to be able to scrape a site for a portion of text and return a ONLINE/OFFLINE answer. I apologize for poor formatting and weird variable names. Thanks for taking a look and helping me out!
#!/bin/bash
printf "" > /Users/USER12/Desktop/domainQueryString_output.txt
domainCurlRequest="curl https://www.google.com/?gws_rd=ssl"
ifStatementConditional="grep 'google.com' /Users/USER12/Desktop/domainQueryString_output.txt | wc -l"
echo $($domainCurlRequest) >> /Users/USER12/Desktop/domainQueryString_output.txt
if [ $ifStatementConditional -eq 2 ] ;
then second_check="online"
else second_check="DOMAIN IS OFFLINE"
fi
echo $second_check
i keep getting the following error when trying to run this script
/Users/USER12/Desktop/domain_status8working.sh: line 6: [: too many arguments
i tried to rewrite another way but got same errors so my logic or syntax or something is off.
Thanks again for taking a look and helping me out!!!
ifStatementConditional="grep 'google.com' /Users/USER12/Desktop/domainQueryString_output.txt | wc -l"
This is a string assignment. You probably want backticks, or the $() construct. Otherwise, $ifStatementConditional will never equal 2
if [ $ifStatementConditional -eq 2 ] ;
This is expanded as:
if [ grep 'google.com' /Users/USER12/Desktop/domainQueryString_output.txt | wc -l -eq 2 ] ;
Which explains your error.
I think you meant that:
#!/bin/bash
curl "https://www.google.com/?gws_rd=ssl" > /Users/USER12/Desktop/domainQueryString_output.txt
ifStatementConditional=$("grep 'google.com' /Users/USER12/Desktop/domainQueryString_output.txt | wc -l")
if [ $ifStatementConditional -eq 2 ] ; then
second_check="online"
else
second_check="DOMAIN IS OFFLINE"
fi
echo $second_check
No need to do printf "" > somefile.txt when you do a curl after, and you append to that file
$() is to capture subshell output. That what was missing here.

Error in shell script if condition [duplicate]

This question already has answers here:
Bash if statement syntax error [duplicate]
(3 answers)
Closed 9 years ago.
I didnt understand what he error here as iam new to shell scripting. Please help me
./bpr: line 8: syntax error near unexpected token `then'
./bpr: line 8: ` if[$(grep -o BPR $file | wc -l) == 1]; then '
You need to add spaces between your [ ], try this:
if [ $(grep -o BPR $file | wc -l) == 1 ]; then
You need a space around your condition:
if [ $(grep -o BPR $file | wc -l) == 1 ]; then
^ ^
1) If you are using bash, you can use the built-in [[ ..]] instead of test ([ ...]) command.
2) You can also avoid wc by using -c option of grep.
if [[ $(grep -c -o BPR $file) == 1 ]]; then
Aside from your syntax errors, you don't need wc either if you don't care that there may be multiple occurrances of BPR in the file:
if grep -o BPR "$file"; then
A couple of things:
You need spaces around [ and ].
You probably don't want to use [ and ].
The if statement runs the command you give it. If the command returns a zero, the then portion of the if statement is executed. If the command returns a non-zero, the else portion (if it exists) is executed.
Try this:
$ if ls some.file.name.that.does.not.exist
> then
> echo "Hey, the file exists!"
> else
> echo "Nope. File isn't there"
> fi
You'll get an output:
ls: some.file.name.that.does.not.exist: No such file or directory
Nope. File isn't there
That first statement, of course is the output of your ls command. The second one is the output from the if statement. The ls ran, but couldn't access that file (it doesn't exist) and returned e 1. That caused the else clause to execute.
Try this:
$ touch foo
$ if ls foo
> echo "Hey, the file exists!"
> else
> echo "Nope. File isn't there"
> fi
You'll get an output:
foo
Hey, the file exists!
Again the first line is your output from ls. Since the file exists, and is statable, ls returned a 0. This caused the if clause to execute, printing the second line.
What if I want to test whether or not a file exists?
You can use the test command:
$ if test -e foo
> then
> echo "Hey, the file exists!"
> else
> echo "Nope. File isn't there"
> fi
If the file foo exists, the test command returns a 0. That means the echo "Hey, the file exists!" will execute. If the file doesn't exist, test will return a 1, and the else clause will execute.
Now do this:
$ ls -il /bin/test /bin/[
10958 -rwxr-xr-x 2 root wheel 18576 May 28 22:27 /bin/[
10958 -rwxr-xr-x 2 root wheel 18576 May 28 22:27 /bin/test
That first number is the inode. If two matching files have the same inode, they are hard linked to each other. The [... ] are merely another name for the test command. The [ is an actual command. That's why you need spaces around it. You also see that if tests whether or not a command succeeds, and doesn't really do boolean checking (the exception is if you use double square brackets like [[ and ]] instead of [ and ]. These are built into the shell and not as builtin commands.)
What you probably want to do is:
if grep -q "BPR" "$file"
then
echo "'BPR' is in '$file'"
fi
The -q flag tells grep to shut its yap. The grep command will return a 0 if the pattern you give it is in the file, and a non-zero (exact value doesn't matter -- as long as it isn't 0) if it can't.
Note I don't need [ ... ] because I am using the output of the grep command to see if I should execute the if clause of that statement.
if you only need to know if the string matches without showing the actual match use
if grep -q 'anystring' file ; then

Shell command - condition based on output of command?

I'm trying to run some shell command if a string is not present in a text file. If I paste this line into the command line if gives me an error.
if [ $(cat textfile.txt | grep "search string") -eq "" ]; then; echo "some string"; fi;
Error:
-bash: [: -eq: unary operator expected
If you use [] for comparison you need to use = instead of -eq. You also need some quotes.
if [ "$(cat textfile.txt | grep 'search string')" = "" ]; then; echo "some string"; fi;
Note that grep can take a filename as argument so the cat is unnecessary. You can also directly use the return value of grep: grep returns 1 if the search string is not found.
if [ "$(grep 'search string' textfile.txt)" ]; then
echo "some string";
fi
An even more compact way would be to use logical and &&.
grep "search string" textfile.txt && echo "some string"
The grep command will return 0 if the requested lines are found (1 if not, 2 if an error), so you can just use:
grep "search string" textfile.txt >/dev/null 2>&1
if [[ $? -ne 0 ]] ; then
echo 'Not found'
fi
If you really wanted to use strings (and you probably shouldn't), you should quote them so that you don't get too many arguments for the [ command:
if [ "$(cat textfile.txt | grep 'search string')" == "" ] ; then
echo "It's not there!"
fi
grep -F -q -e 'search string' textfile.txt || echo 'Not found'
Note:
-F prevents the interpretation of the search string as a regular expression.
-q suppresses all output and returns immediately after the first instance was found, making the search much faster if the string occurs at the beginning of a large file.
-e specifies the pattern explicitly, allowing patterns that start with a dash.
Use single quotes unless you want variable substitutions.
No need for the square brackets in this case. Since [ is actually a command, any command can be used where you would use it. So here, we can use grep. There's no need to use cat since grep will accept filenames as arguments. Also, you have two too many semicolons.
if grep -q "search string" textfile.txt; then echo "some string"; fi
or
if grep "search string" textfile.txt > /dev/null 2>&1; then echo "some string"; fi

Trying to test space in filesystem on Unix

I need to check if I Filesystem exists, and if it does exist there is 300 MB of space in it.
What I have so far:
if [ "$(df -m /opt/IBM | grep -vE '^Filesystem' | awk '{print ($3)}')" < "300" ]
then
echo "not enough space in the target filesystem"
exit 1
fi
This throws an error. I don't really know what I'm doing in shell.
My highest priority is AIX but I'm trying to get it to work for HP and Sun too.
Please help.
-Alex
Here is the code I got working.
if [ "$(df -m /opt/IBM/ITM | awk 'NR==2{print ($3)}')" -lt "300" ]
then
echo "not enough space in the target filesystem"
exit 1
fi
How about posting the error? Anyway, try the following syntax, ie. double brackets and no double quotes:
if [[ $(...) < 300 ]]; then
...
fi
From man bash:
[[ expression ]]
Return a status of 0 or 1 depending on the evaluation of the conditional
expression expression.

Resources