How to split an output to two files with grep

grepio-redirection

I have a script mycommand.sh that I can't run twice. I want to split output to two different files one file containing the lines that match a regex and one file containing the lines that don't match a regex. What I wish to have is basically something like this:

./mycommand.sh | grep -E 'some|very*|cool[regex].here;)' --match file1.txt --not-match file2.txt

I know I can just redirect the output to a file and then to two different greps with and without -v option and redirect their output to two different files. But I was jsut wondering if it was possible to do it with one grep.

So, Is it possible to achieve what I want in a single line?

Best Answer

There are many ways to accomplish this.

Using awk

The following sends any lines matching coolregex to file1. All other lines go to file2:

./mycommand.sh | awk '/[coolregex]/{print>"file1";next} 1' >file2

How it works:

  1. /[coolregex]/{print>"file1";next}

    Any lines matching the regular expression coolregex are printed to file1. Then, we skip all remaining commands and jump to start over on the next line.

  2. 1

    All other lines are sent to stdout. 1 is awk's cryptic shorthand for print-the-line.

Splitting into multiple streams is also possible:

./mycommand.sh | awk '/regex1/{print>"file1"} /regex2/{print>"file2"} /regex3/{print>"file3"}'

Using process substitution

This is not as elegant as the awk solution but, for completeness, we can also use multiple greps combined with process substitution:

./mycommand.sh | tee >(grep 'coolregex' >File1) | grep -v 'coolregex' >File2

We can also split up into multiple streams:

./mycommand.sh | tee >(grep 'coolregex' >File1) >(grep 'otherregex' >File3) >(grep 'anotherregex' >File4) | grep -v 'coolregex' >File2
Related Question