How to split an output to two files with grep?

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

sed -n -e '/pattern_1/w file_1' -e '/pattern_2/w file_2' input.txt

w filename - write the current pattern space to filename.

If you want all matching lines to go to file_1 and all non-matching lines to file_2, you can do:

sed -n -e '/pattern/w file_1' -e '/pattern/!w file_2' input.txt

or

sed -n '/pattern/!{p;d}; w file_1' input.txt > file_2

Explanation

  1. /pattern/!{p;d};
    • /pattern/! - negation - if a line doesn't contain pattern.
    • p - print the current pattern space.
    • d - delete pattern space. Start next cycle.
    • so, if a line doesn't contain pattern, it prints this line to the standard output and picks the next line. Standard output is redirected to the file_2 in our case. The next part of the sed script (w file_1) doesn't reached while the line doesn't match to the pattern.
  2. w file_1 - if a line contains pattern, the /pattern/!{p;d}; part is skipped (because it is executed only when pattern doesn't match) and, thus, this line goes to the file_1.