How to write noncapturing groups in egrep - grep

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

Related

Combine multiple grep regular expression into one command

Consider this input file:
bam/pfg413T.GRCh38DH.target.bai
bam/pfg413T.GRCh38DH.target.bam
bam/pfg413T.GRCh38DH.target.bam
bam/pfg416G.GRCh38DH.target.bai
bam/pfg416G.GRCh38DH.target.bam
How can I combine the following multiple grep -E into one grep -E pipe ?
readlink -f exomesinglesample_out/bam/pfg* | grep -E 'pfg[0-9]*G' | grep -E 'bam$'

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"

Running `bash` using docker exec with xargs command

I've been trying to execute bash on running docker container which has specific name as follows. --(1)
docker ps | grep somename | awk '{print $1 " bash"}' | xargs -I'{}' docker exec -it '{}'
but it didn't work and it shows a message like
"docker exec" requires at least 2 argument(s)
when I tried using command as follows --(2)
docker ps | grep somename | awk '{print $1 " bash"}' | xargs docker exec -it
it shows another error messages like
the input device is not a TTY
But when I tried using $() (sub shell) then it can be accomplished but I cannot understand why it does not work with the two codes (1)(2) above (using xargs)
Could any body explain why those happen?
I really appreciate any help you can provide in advance =)
EDIT 1:
I know how to accomplish my goal in other way like
docker exec -it $(docker ps | grep perf | awk '{print $1 " bash"}' )
But I'm just curious about why those codes are not working =)
First question
"docker exec" requires at least 2 argument(s)
In last pipe command, standard input of xargs is, for example, 42a9903486f2 bash. And you used xargs with -I (replace string) option.
So, docker recognizes that 42a9903486f2 bash is a first argument, without 2nd argument.
Below example perhaps is the what you expected.
docker ps | grep somename | awk '{print $1 " bash"}' | xargs bash -c 'docker exec -it $0 $1'
Second question
the input device is not a TTY
xargs excutes command on new child process. So you need to reopen stdin to child process for interactive communication. (MacOS: -o option)
docker ps | grep somename | awk '{print $1 " bash"}' | xargs -o docker exec -it
This worked for me:
sudo docker ps -q | xargs -I'{}' docker exec -t {} du -hs /tmp/
The exec command you run is something like this:
docker exec -it 'a1b2c3d4 bash'
And that is only one argument, not two. You need to remove the quotes around the argument to docker exec.
... | xargs -I'{}' docker exec -it {}
Then you will exec properly with two arguments.
docker exec -it a1b2c3d4 bash
------ ---
first arg ^ ^ second arg

Grep with color and multiple excludes

I would like to do a grep to dig through my code hierarchy and look for the term "x", but color the results and exclude annoying terms. Right now I do:
grep -Rn --color x * | grep -v -e html -e svn -e test -e doc -e y
The problem is that this loses the matching color because of the pipe. Is there anyway to make this one statement so that the coloring isn't lost?
Specify --color=always to preserve color formatting through pipes:
grep --color=always x * | grep -v -e html -e svn -e test -e doc -e y
And later on if you happen to need to pipe the result into a file and need to remove the escape characters that format color, here's a nifty sed script you can pipe your results through to remove the escape charaters:
sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"
(Note that you need -E option instead of -r for OS X)
You can try repeating the color search:
grep -Rn --color x * | grep -v -e html -e svn -e test -e doc -e y | grep --color x

Combining many greps in a single grep call

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/'

Resources