Yuqi Jin
Yuqi Jin

Reputation: 53

Multiple "grep...then..." in bash

I'm writing a bash script which monitoring the output of script A, and matching keyword by "grep" command. If successfully found the keyword, echo something. Here is the script I have:

if script_A | grep -q 'keyword'; 
then
echo 'Found A!'

The script function well if only one condition. However I cannot find a way to match several keywords, and using "if...elif...else" to control the echo content for different conditions.

Here is the logic I'm trying to achieve:

script_A |
if grep 'keyword_A';
then echo 'Found A!'
elif grep 'keyword_B';
then echo 'Found B!'
else echo 'Found Nothing!'

Thanks!

Upvotes: 0

Views: 926

Answers (4)

Yuqi Jin
Yuqi Jin

Reputation: 53

In case anyone need it, I found the workable answer:

#!/bin/bash

 function test() {
   echo "test"
  sum=0
  while true
  do
    stat_date=`date`
    echo $stat_date
  done
}

function checkcondition() {
 while read data; do
  if [[ $data == *"10:52:59"* ]]; then
  echo "Found the time!";

  elif [[ $data == *"hi"* ]]; then
  echo "Found hi!";

  else
  echo "Nothing";

  fi
  done;

}

test | checkcondition

The code will keeping generating time string. And the checkcondition function will receive the output. Whenever the output string contains "10:52:59", it will print "Found the time!", otherwise print "Nothing".

Upvotes: 0

Charles Duffy
Charles Duffy

Reputation: 295403

Each write can have only one reader consume if. That reader can then create multiple copies of the data it read (like tee does), but there has to be just one thing on the other end initially.

A more conventional approach would be to have the shell be that one reader, as in:

output=$(script_A)
if grep -q 'keyword_A' <<<"$output"; then
  echo 'Found A!'
elif grep -q 'keyword_B' <<<"$output"; then
  echo 'Found B!'
else
  echo 'Found nothing!'
do

...or, if you need to stream output continuously:

script_A | {
  found=0
  while IFS= read -r line; do
    if [[ $line = *keyword_A* ]]; then
      echo 'Found A!'; found=1; break
    elif [[ $line = *keyword_B* ]]; then
      echo 'Found B!'; found=1; break
    fi
  done
  if (( found == 0 )); then
    echo 'Reached end of input and found nothing!'
  fi
}

Upvotes: 2

Walter A
Walter A

Reputation: 20002

You can use the Bash rematch:

if [[ "demo_rematch" =~ [st] ]]; then
  echo "Matched from regexpr [st] is the letter ${BASH_REMATCH}!"
fi

With your single letter keywords you can do something like

# grep [YES] is the same as grep [ESY]
for regex in '[AB]' '[YES]' '[NO]'; do
  echo "$regex"
  if [[ "$(printf "keyword_%s\n" {A..G})" =~ keyword_$regex ]]; then
    echo "Found ${BASH_REMATCH/keyword_}!"
  else
    echo "Found Nothing!"
  fi
done

In real live your keywords might be more complicated. You can still use the same construction, but now I will not use the string "keyword_".

regex='(foo|bar|A|B|not me|no match|bingo)'
echo "$regex"
for script_A in "String with foos" "String with bar" "String with A" "String with B" "Nothing here" "Please ignore me" "and bingo"; do
  if [[ "${script_A}" =~ $regex ]]; then
    echo "Found ${BASH_REMATCH}!"
  else
    echo "Found Nothing!"
  fi
done

Upvotes: 0

William Pursell
William Pursell

Reputation: 212248

If you are happy just seeing the output of grep (instead of your cusom messages), you can just do:

if ! script_A | grep -e 'keyword_A' -e 'keyword_B'; then
    echo 'Found Nothing'
fi

It's somewhat difficult to directly manipulate the output of grep in the pipeline, but you could get custom messages with:

if ! script_A | grep -o -e 'keyword_A' -e 'keyword_B'; then
    echo 'Nothing'
fi | sed -e 's/^/Found /' -e 's/$/!/'

Upvotes: 0

Related Questions