Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grep without filtering

Tags:

grep

bash

shell

How do I grep without actually filtering, or highlighting?

The goal is to find out if a certain text is in the output, without affecting the output. I could tee to a file and then inspect the file offline, but, if the output is large, that is a waste of time, because it processes the output only after the process is finished:

command | tee file
file=`mktemp`
if grep -q pattern "$file"; then
  echo Pattern found.
fi
rm "$file"

I thought I could also use grep's before (-B) and after (-A) flags to achieve live processing, but that won't output anything if there are no matches.

# Won't even work - DON'T USE.
if command | grep -A 1000000 -B 1000000 pattern; then
  echo Pattern found.
fi

Is there a better way to achieve this? Something like a "pretend you're grepping and set the exit code, but don't grep anything".

(Really, what I will be doing is to pipe stderr, since I'm looking for a certain error, so instead of command | ... I will use command 2> >(... >&2; result=${PIPESTATUS[*]}), which achieves the same, only it works on stderr.)

like image 782
Mihai Danila Avatar asked Sep 16 '25 11:09

Mihai Danila


2 Answers

If all you want to do is set the exit code if a pattern is found, then this should do the trick:

awk -v rc=1 '/pattern/ { rc=0 } 1; END {exit rc}' 

The -v rc=1 creates a variable inside the Awk program called rc (short for "return code") and initializes it to the value 1. The stanza /pattern/ { rc=0 } causes that variable to be set to 0 whenever a line is encountered that matches the regular expression pattern. The 1; is an always-true condition with no action attached, meaning the default action will be taken on every line; that default action is printing the line out, so this filter will copy its input to its output unchanged. Finally, the END {exit rc} runs when there is no more input left to process, and ensures that awk terminates with the value of the rc variable as its process exit status: 0 if a match was found, 1 otherwise.

The shell interprets exit code 0 as true and nonzero as false, so this command is suitable for use as the condition of a shell if or while statement, possibly at the end of a pipeline.

like image 172
Mark Reed Avatar answered Sep 19 '25 08:09

Mark Reed


To allow output with search result you can use awk:

command | awk '/pattern/{print "Pattern found"} 1'

This will print "Pattern found" when pattern is matched in any line. (Line will be printed later)

If you want Line to print before then use:

command | awk '{print} /pattern/{print "Pattern found"}'

EDIT: To execute any command on match use:

command | awk '/pattern/{system("some_command")} 1'

EDIT 2: To take care of special characters in keyword use this:

command | awk -v search="abc*foo?bar" 'index($0, search) {system("some_command"); exit} 1'
like image 32
anubhava Avatar answered Sep 19 '25 08:09

anubhava