13

Is there a script/program/utility already available for the following requirement in a optimised way?

someCommand |
   tee >(grep "pattern" > LinesWhichMatch) |
   grep -v "pattern" > LinesWhichDoesNotMatch

3 Answers 3

16

You could use awk for that.

command | awk '{ if (/pattern/) { print > "match" } else { print > "nomatch" } }'
2
  • 1
    I'm not completely familiar with awk but at what point does it evaluade the > ? If it's evaluated each time the conditional applies, you'd wind up with two one-line files... Sep 22, 2011 at 11:40
  • 1
    @Shadur > prints all output to the file, overwriting existing files. It isn't evaluated in such a way that it will result in any new lines overwriting old output from the same instance of awk. That is, if there are multiple matches, the file "match" will contain each match separated by OFS. The difference between > and >> exists in treatment of existing files.
    – Chris Down
    Sep 22, 2011 at 11:43
11

Here is a sed example:
Note: sed's w command will overwrite an existing file each time the script is run, but only if that particular write command is triggered; hence the rm

rm -f file-{yes,not}  
sed -ne '/pattern/bY; w file-not' -e 'b; :Y; w file-yes' file
2
  • 1
    Nice. Without branching: sed -n '/PATTERN/p;//! w file-not' infile >file-yes Apr 4, 2015 at 22:29
  • Is there a sed version that also allows a substitution to happen on the matched lines? I can't figure out how to add an s command...
    – tom
    Jul 30, 2021 at 23:46
6

You can append files in awk:

awk '{if (/pattern/) print >>"matched"; else print >>"unmatched"; }

or shorter:

awk '{print >>(/pattern/?"matched":"unmatched")}'
1
  • His example shows that he wants to overwrite the files if they exist, not append.
    – Chris Down
    Sep 22, 2011 at 0:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .