Checking if output of a command contains a certain string in a shell script

BashShellGrep

Bash Problem Overview


I'm writing a shell script, and I'm trying to check if the output of a command contains a certain string. I'm thinking I probably have to use grep, but I'm not sure how. Does anyone know?

Bash Solutions


Solution 1 - Bash

Testing $? is an anti-pattern.

if ./somecommand | grep -q 'string'; then
  echo "matched"
fi

Solution 2 - Bash

Test the return value of grep:

./somecommand | grep 'string' &> /dev/null
if [ $? == 0 ]; then
   echo "matched"
fi

which is done idiomatically like so:

if ./somecommand | grep -q 'string'; then
   echo "matched"
fi

and also:

./somecommand | grep -q 'string' && echo 'matched'

Solution 3 - Bash

Another option is to check for regular expression match on the command output.

For example:

[[ "$(./somecommand)" =~ "sub string" ]] && echo "Output includes 'sub string'"

Solution 4 - Bash

A clean if/else conditional shell script:

if (ls | grep '$1') then echo "exists" else echo "doesn't exist" fi

Solution 5 - Bash

SHORT ANSWER

All the above (very excellent) answers all assume that grep can "see" the output of the command, which isn't always true:

SUCCESS can be sent to STDOUT while FAILURE to STDERR.

So depending on which direction you test, your grep can fail. That's to say that if you are testing for the case of FAILURE you must redirect the output of the command to STDOUT using 2>&1 in such a case as this.

LONGER ANSWER w/ PROOFS

I had what I thought was a very simple test in a bash script using grep and it kept failing. Much head scratching followed. Use of set -x in my script revealed that the variable was empty! So I created the following test to understand how things were breaking.

NOTE: iscsiadm is a Linux tool from the "open-iscsi" package used to connect/disconnect a host to SAN storage. The command iscsiadm -m session is used to show if any LUN connections are established):

#!/bin/bash

set -x

TEST1=$(iscsiadm -m session)
TEST2=$(iscsiadm -m session 2>&1)
echo
echo 'Print TEST1'
echo $TEST1
echo
echo 'Print TEST2'
echo $TEST2
echo

If a LUN WAS connected, BOTH variables were successfully populated with values:

Print TEST1
tcp: [25] 192.168.X.XX:3260,1 iqn.2000-01.com.synology:ipdisk.Target-LUN1 (non-flash) tcp: [26] 192.168.X.XX:3260,1 iqn.2000-01.com.synology:storagehost.Target-LUN1 (non-flash)

Print TEST2
tcp: [25] 192.168.X.XX:3260,1 iqn.2000-01.com.synology:ipdisk.Target-LUN1 (non-flash) tcp: [26] 192.168.X.XX:3260,1 iqn.2000-01.com.synology:storagehost.Target-LUN1 (non-flash)

However, if a LUN WASN'T connected, iscsiadm sent the output to STDERR, and only the "TEST2" variable was populated where we had redirected to STDOUT using 2>&1; "TEST1" variable which had no redirection to STDOUT was empty:

iscsiadm: No active sessions.

Print TEST1


Print TEST2
iscsiadm: No active sessions.

CONCLUSION

If you have a funky, half-broken- works in one direction but not the other- situation such as this, try the above test replacing iscsiadm with your own command and you should get the proper visibility to rewrite your test to work correctly.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1118764View Question on Stackoverflow
Solution 1 - BashmatView Answer on Stackoverflow
Solution 2 - BashperrealView Answer on Stackoverflow
Solution 3 - BashNoam ManosView Answer on Stackoverflow
Solution 4 - BashEhsan BarkhordarView Answer on Stackoverflow
Solution 5 - BashF1LinuxView Answer on Stackoverflow