Using GREP in IF Statement

Hello All,
I have 2 different pieces of code, I am confused why the Code1 is giving me the correct result where as the Code2 is not giving me correct result. It gives me always result as "Failure" irrespective of the "ERROR" word exists in logfile or not. may I know the reason why? I am using Bash shell in Linux OS.

Code1:

#!/bin/bash
sqlplus -s FCSDWH_STG/FCSDWH_STG@dwdev <<EOF > /home/infrmtca/bin/logfile
exec today_is;
EOF
        if `grep -q "ERROR" /home/infrmtca/bin/logfile` ;
        then
                echo "Success"
        else
                echo "Failure"
        fi

Code2:

#!/bin/bash
sqlplus -s FCSDWH_STG/FCSDWH_STG@dwdev <<EOF > /home/infrmtca/bin/logfile
exec today_is;
EOF
        if [ `grep -q "ERROR" /home/infrmtca/bin/logfile` ]
        then
                echo "Success"
        else
                echo "Failure"
        fi

My content of "/home/infrmtca/bin/logfile" is below

BEGIN today_is; END;

      *
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00905: object FCSDWH_STG.TODAY_IS is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

Thank you

I assume you want to print message: Failure when you find the pattern: ERROR in your file.

Few corrections and modifications:

if grep -q "ERROR" /home/infrmtca/bin/logfile 
then
      echo "Failure"
else
      echo "Success"
fi

But why is it not working when I put the same in like [if grep -q "ERROR" /home/infrmtca/bin/logfile]

Error:

/home/infrmtca/bin/test.sh: line 5: [: too many arguments
Failure

Please note that square brackets [] that contain the statement are a synonym for the 'test' command.

So it is expecting a valid expression and it is failing because the command that you put inside doesn't meet the criteria.

This is why you don't need a square bracket [] to wrap the command.

The grep command returns the exit status 0 or non-zero which if statement can check and transfer the control to corresponding action.

(1)

Isn't greping for a string "ERROR" is also a test? what do you mean by test? you mean comparing 2 variables or values using -eq for numbers and == for strings or a -z or -n for zero & nonzero byte strings, something like that...Can you please explain a bit more with example

(2) I am trying the below script to check 2 conditions

#!/bin/bash
PATH="/db_apps/informatica/infa951/server/infa_shared/BWParam/wf_GenerateXMLDataFile.txt"
UNINUM="92500"
echo $UNINUM

        if  /bin/grep -q "UNINUM" $PATH -a -z ${UNINUM}
        then
                echo "success"
        else
                echo "failure"
        fi

But it always returns success, i am confused.

Thank you.

if [ 4 = 4 ]
then
  echo "true"
fi

is the same as

if test 4 = 4
then
  echo "true"
fi

grep, like test, sets an exit status that "if" can use.
But grep is a different command.

Indeed [ ] is not an operator; the [ is the test command plus it wants a ] as last argument.

type test
test is a shell builtin
type \[
[ is a shell builtin

Is there a way for me to combine a grep command and an expression statement and pass the result to IF statement like below. I am still trying to make the below script work.

#!/bin/bash
PATH="/db_apps/informatica/infa951/server/infa_shared/BWParam/wf_GenerateXMLDataFile.txt"
UNINUM="92500"
echo $UNINUM

        if  /bin/grep -q "UNINUM" $PATH -a -z ${UNINUM}
      #if  [ `/bin/grep -q "UNINUM" $PATH` -a -z ${UNINUM} ]
        then
                echo "success"
        else
                echo "failure"
        fi

---------- Post updated at 03:36 PM ---------- Previous update was at 03:32 PM ----------

I think i got it

#!/bin/bash
PATH="/db_apps/informatica/infa951/server/infa_shared/BWParam/wf_GenerateXMLDataFile.txt"
UNINUM="92500"
echo $UNINUM

        if  ! `/bin/grep -q "UNINUM" $PATH` && [ ! -z ${UNINUM} ]
        then
                echo "success"
        else
                echo "failure"
        fi

-a and -z work inside the test command. -a is logical AND.
Here you need &&, the shell's logical AND.
Do not use `command in backticks`! It runs the command output in a subshell!
No harm *here* because grep -q suppresses the output. But generally confusing and risky.
Last but not least, it is recommended to "quote" variables in command arguments.
Not required *here* because you set them to sane values.

echo $UNINUM
[ ! -z ${UNINUM} ]

do odd things if UNINUM has a * or a space character.

echo "$UNINUM"
[ ! -z "$UNINUM" ]

are safe.

As an old-schooler and purely a rudimentary level scripter, I typically issue the command, then test the result.

grep -q "ERROR" /home/infrmtca/bin/logfile
if [ "$?" -eq 0 ]; then
   echo "Success"
else
   echo "Failure"
fi

That was the way I was taught to construct IF statements, waa...aaay back when.

It's just seems clearer what is going on, particularly for intro/novice readers. It sounds like "[]" is no longer required though. Is that the case?

2 Likes

Maybe to not exceed the 80 characters terminal width?
Since Bourne shell 1.0 there is

man sh
...
if list ; then list ; [ elif list ; then list ; ] ... [ else
     list ; ]  fi
...
1 Like

Your comments raised few doubts in my code, can you please guide me here

1) I am always using the flower brackets for all variables in my shell script like ${VAR}, is that a wrong approach? one issue i just learned is without double quotes the newlines are lost to word split, are there any other drawbacks before i go ahead and replace everywhere in my scripts?

2) I have the following piece code which i am executing via shell script, i am not suppose to use the backticks since it opens up and executes the code in a new sub shell? this works fine for me and serves the purpose

#### SECOND UPDATE OF VALIDATION STATUS IN FEED_PROCESS_LOG TABLE ####

        logit "Updating the Validation Status Field in ${DBSTGUSER}.FEED_PROCESS_LOG Table as COMPLETED With Matching Parameters"
        logit "UNINUM :: ${UNINUM} PROVIDER :: ${PROVIDER} EXTRACT_DT :: ${EXTRACT_DT} VER_NUM :: ${VER_NUM}"

        `${ORACLE_HOME}/bin/sqlplus ${DBSTGUSER}/${DBSTGPASS}@${DBSRC} <<EOF >> ${UPD_FEED_PROC_LOG}
        spool ${UPD_SQL2}
        UPDATE ${DBSTGUSER}.FEED_PROCESS_LOG SET VALIDATION_STATUS='COMPLETED'
        WHERE UNINUM='${UNINUM}' and PROVIDER='${PROVIDER}' and EXTRACT_DT='${EXTRACT_DT}'
        and VER_NUM=${VER_NUM} and ACT_END_DT IS NULL  AND VALIDATION_STATUS='RUNNING';
        spool off;
        COMMIT;
        EXIT;
        EOF`

        if grep -q "ERROR" ${UPD_FEED_PROC_LOG}
        then
                logit "${DBSTGUSER}.FCA_HASH_TOTALS_PKG.HASH_TOTALS_COMPUTE Procedure Failed"
                logit "Please Check ${UPD_FEED_PROC_LOG} Log File For Detailed Information"

                exit 11
        else
                logit "${DBSTGUSER}.FCA_HASH_TOTALS_PKG.HASH_TOTALS_COMPUTE Procedure Completed Successfully"
                logit "Please Check ${UPD_FEED_PROC_LOG} Log File For Detailed Information"
        fi

Thank you.

${VAR} encapsulation is normally not needed.
It is independent of the quoting: "$VAR" is the same as "${VAR}" .
In some cases the quoting eliminates the need of ${VAR} :
$VARx can be "$VAR"x instead of "${VAR}x"
Quoting is only needed in command arguments:

for p in $VAR  # not a command, also "$VAR" would be one item
VAR2=$VAR  # an assignment is not a command
case $VAR in  # case is not a command

In your example it does no harm because stdout is redirected in >> ${UPD_FEED_PROC_LOG}
Nevertheless you should remove the backticks. (Overhead, confusing, risk if the redirection is removed or further code is added.)

If i remove the backticks i am seeing all the text or lines (if statements....etc) from there and after that turned into red color, i thought color changed because my syntax in the script was wrong? do you know why this behaviour?

Hi Arien,

This could owe to various factors one of them being you putty settings.
Just try unalias this would help getting everything in simple black and white.
I do not recommend or trust the colours in vi they kind of annoy me so i keep them simple in black and white.
If your code has a syntax issue it will obivously give that when you execute your script if thats not the case your code has no syntactical issues for sure

I am ok with the colors as it kind of alerts me, by the way it indeed errored out when i execute the main script, i am trying to see why its happening.

syntax error: unexpected end of file

Probably you are missing to end a loop some where check for a missing fi for if or may be a closing bracket.
Cant help much without the seeing the script the above are just the most likely reasons.

Looks like its formattting issue as my below code has tabs infront of each line while passing input to EOF. when i remove the tabs text color looks good as expected and script executes fine. How can i make the shell ignore the tabs?

        ${ORACLE_HOME}/bin/sqlplus ${DBSTGUSER}/${DBSTGPASS}@${DBSRC} <<EOF > ${UPD_FEED_PROC_LOG}
        spool ${UPD_SQL1}
        UPDATE ${DBSTGUSER}.FEED_PROCESS_LOG SET VALIDATION_STATUS='RUNNING'
        WHERE UNINUM='${UNINUM}' and PROVIDER='${PROVIDER}' and EXTRACT_DT='${EXTRACT_DT}'
        and VER_NUM=${VER_NUM} and ACT_END_DT IS NULL  AND (VALIDATION_STATUS IS NULL OR VALIDATION_STATUS='RUNNING');
        spool off;
        COMMIT;
        EXIT;
        EOF

Hi can you please Change the "<<" to "<<-" it will cause bash to ignore the leading tabs (but not spaces) in the here script.

1 Like