Combining many greps in a single grep call - grep

I've a script where I've to check if a process is running by its name and I'm doing it using ps and grep. The problem is that I've to grep many things to avoid to find false positive.
By now, I've a grep chain that looks as follow:
ps -ef | grep -i $process_name | grep -i perl | grep -v do_all | grep -v grep
Four greps. Three of them are there to avoid false positive.
I would like to know if there's a way to avoid such 'piping chain' and use a single grep to achieve the same result.
Though some of you could answer that there are cleaner way to find out if a process exists, I would like the same to have an answer to this question, just to better understand the usage of the grep command.

There's no real reason to avoid chaining them, is there?
If you really wanted to you could combine them with | in egrep:
ps -ef | egrep -i "$process_name|perl" | egrep -v 'do_all|grep'

Here's one way using GNU awk:
ps -ef | awk -v process="$process_name" 'BEGIN { IGNORECASE=1 } $0 ~ process && /perl/ && !/do_all/'

Related

Check docker instance in Bash

Having docker ps -a
I want to match the NAMES VERSION and STATUS.
docker ps -a --format "{{.Image}}\t{{.Status}}" | awk -F$"\t" '{printf "%s|%s\n", $1, $2}'
Output:
registry.com/project/glass/glass_front:2.2.15.4|Up 6 days
registry.com/project/glass/glass_proxy:2.2.15.4|Up 6 days
registry.com/project/glass/glass_modeles_front:2.1.5.2|Up 6 days
How can i modify my command to have this:
glass_front | 2.2.15.4 | Up 6 days
glass_proxy | 2.2.15.4 | Up 6 days
glass_modeles_front| 2.1.5.2 | Up 6 days
Try using colon as the separator in the docker ps command, then use sed to transform the colon to pipe and remove the prefix:
docker ps -a --format "{{.Image}}:{{.Status}}" \
| sed -e 's/:/ | /g' -e 's,^.*/,,'
Could you please try following, not tested it as don't have docker command. Its based on completely shown sample output of OP only.
docker ps -a --format "{{.Image}}\t{{.Status}}" \
| awk -F'\t' '{num=split($1,arr,"[/:]");print arr[num-1],arr[num],$2}'
OR(only using field separator capability of awk)
docker ps -a --format "{{.Image}}\t{{.Status}}" \
| awk -F"[/:\t]" '{print $4,$5,$NF}'
Explanation(1st solution): Running docker program(what OP shown) then passing its output as an input to awk command. In awk command setting field separator as TAB. Then splitting 1st field into an array(arr) with delimiter of /,:, then finally printing arr's 2nd last and last items here with 2nd field of current line.

grep: constructing a regex pattern to exclude several groups

I have a folder with three files:
$ ls
aaa.txt abc.txt def.txt
If I want to grep the output excluding the abc.txt file I can do:
$ ls | grep -v 'abc'
aaa.txt
def.txt
If I want to exclude two files I can do:
$ ls | grep -v 'abc' | grep -v 'def'
aaa.txt
But how can I do this using one regex and one grep invocation?
This does not work:
$ ls | grep -v '[(abc)(def)]'
neither does this:
$ ls | grep -v "abc|def"
Use the ERE(Extended Regular Expression) pattern for the alternation match | which is not enabled by default in BRE (which grep uses by default)
grep -vE "abc|def"
or use the extended grep, i.e. egrep which enables the ERE by default
egrep -v "abc|def"

How to write noncapturing groups in egrep

The following command does not correctly capture the 16714 from 16714 ssh -f -N -T -R3300:localhost:22
egrep -o '^[^ ]+(?= .*[R]3300:localhost:22)'
(However swapping to grep does if you use the -P flag. I was expecting egrep to be able to handle this)
grep -P forces grep to use the Perl regexp engine.
egrep is the same as grep -E and it forces grep to use the ERE (extended regular expression) engine, that does not support lookahead.
You can find a quick reference of the differences between Perl and ERE (and others) here : http://www.greenend.org.uk/rjk/tech/regexp.html
To handle this with POSIX grep, you would use grep to isolate the lines of interest and then use cut to isolate the fields of interest:
$ echo "16714 ssh -f -N -T -R3300:localhost:22" | grep 'R3300:localhost:22' | cut -d' ' -f1
16714
Or, just use awk:
$ echo "16714 ssh -f -N -T -R3300:localhost:22" | awk '/R3300:localhost:22/{print $1}'
16714

pipe tcpdump output to grep multiline pattern

I want to grep a multiline pattern from tcpdump output like the following:
sudo tcpdump -A -s0 | grep -Pzo 'foo.*\n.*bar'
However, it does not seem to work. But it works if I dump the data into a file and then grep the file. How can I make the command using pipe working?
Try to add -l:
-l Make stdout line buffered. Useful if you want to see the data while capturing it.
E.g.,
tcpdump -l | tee dat
tcpdump -l > dat & tail -f dat
I still don't get why the grep does not work above even with -l option for tcpdump, but I found this stackoverflow post How to find patterns across multiple lines using grep?. So I tried pcregrep, and it worked.
sudo tcpdump -A -s0 | pcregrep -Mo "foo.*\n.*bar"
I was having problems piping the output to tail even with the -l switch as well. I was able to solve my problem by using multitail instead of tail -F.
This worked for me: multitail -l "tcpdump -li eth0"

Inspect stdout from the middle of chained apps

Consider this example chain:
cat foo.txt | grep -v foo | grep -v bar | grep -v baz
I'd like to inspect the contents stdout of the second grep as well as the resulting stdout:
cat foo.txt | grep -v foo | grep -v bar | UNKNOWN | grep -v baz
So I need a tool, UNKNOWN, that for instance dumps the contents of stdout to a file and also passes stdout along the chain.
Does the tool, UNKNOWN, exists (both Windows and Linux answers are relevant) ?
I think there's a thing call 'tee' that gives you that.
Update reflecting comment from Bob:
cat foo.txt | grep -v foo | grep -v bar | tee -a inspection.txt | grep -v baz
Unable to give it a shot, but like Gabriel and Bob pointed out, the command $ tee (man tee) will help you out. The tee command will take input and echo it to stdout, as well as files. As Bob said in his comment:
cat foo.txt | grep -v foo | grep -v bar | tee -a inspection.txt | grep -v baz
Will take the output from grep -v bar and put it to stdout, as well as inspection.txt. The -a flag causes it to append to inspection rather than create a whole new file.

Resources