6

I have some data where the 4th column will either be frz or -. I would like to find all lines where the 4th column is frz only if the 4th column on the next line is - and then print both lines.

Sample input:

2018-04-09T14:15:23.366Z  7 multi -   uuid1 uuid2 uuid3 -
2018-04-09T14:15:23.978Z  8 multi frz   uuid1 uuid3 -        -
2018-04-09T14:29:35.826Z  8 multi frz   uuid1 uuid3 uuid2 -
2018-04-09T17:19:01.901Z  8 multi frz uuid1 uuid3 uuid2 -
2018-06-03T22:12:38.688Z  8 multi -   uuid1 uuid3 uuid2 -
2018-06-28T00:35:54.338Z  9 multi -   uuid1 uuid2 -        -
2018-06-28T00:47:51.679Z  9 multi -   uuid1 uuid2 uuid3 -
2018-06-28T00:47:51.720Z 10 multi -   uuid1 uuid3 -        -
2018-06-28T00:47:58.863Z 10 multi -   uuid1 uuid3 uuid2 -
2018-06-28T16:29:01.624Z 10 multi frz uuid1 uuid3 uuid2 -
2018-06-28T17:29:01.624Z 10 multi - uuid1 uuid3 uuid2 -

Expected output:

2018-04-09T17:19:01.901Z  8 multi frz uuid1 uuid3 uuid2 -
2018-06-03T22:12:38.688Z  8 multi -   uuid1 uuid3 uuid2 -
2018-06-28T16:29:01.624Z 10 multi frz uuid1 uuid3 uuid2 -
2018-06-28T17:29:01.624Z 10 multi - uuid1 uuid3 uuid2 -

I've found a few awk commands to print the line after a match but I can't figure out how to match both lines and print both.

What I currently have:

$ awk 'f{print;f=0} $4=="frz"{f=1}' input
2018-04-09T14:29:35.826Z  8 multi frz   uuid1 uuid3 uuid2 -
2018-04-09T17:19:01.901Z  8 multi frz uuid1 uuid3 uuid2 -
2018-06-03T22:12:38.688Z  8 multi -   uuid1 uuid3 uuid2 -
2018-06-28T17:29:01.624Z 10 multi - uuid1 uuid3 uuid2 -

4 Answers 4

5

How about:

awk '$4=="-" && prev4=="frz" {print prevline; print} {prev4 = $4; prevline=$0}' file
1
  • ty sir, exactly what I need!
    – jesse_b
    Commented Jun 28, 2018 at 17:35
4

If you have GNU grep and your pattern doesn't occur elsewhere in the data, you can try this :

grep -A1 frz | grep -vB1 frz

Explanation

The first grep captures all lines where the pattern occurs, plus the next one :

-A NUM, --after-context=NUM Print NUM lines of trailing context after matching lines. Places a line containing a group separator (--) between contiguous groups of matches.

The output of this first command on your sample input is :

2018-04-09T14:15:23.978Z  8 multi frz   uuid1 uuid3 -        -
2018-04-09T14:29:35.826Z  8 multi frz   uuid1 uuid3 uuid2 -
2018-04-09T17:19:01.901Z  8 multi frz uuid1 uuid3 uuid2 -
2018-06-03T22:12:38.688Z  8 multi -   uuid1 uuid3 uuid2 -
--
2018-06-28T16:29:01.624Z 10 multi frz uuid1 uuid3 uuid2 -
2018-06-28T17:29:01.624Z 10 multi - uuid1 uuid3 uuid2 -

Then the second command searches for lines not containing the pattern, and prints them with the line before :

-B NUM, --before-context=NUM Print NUM lines of leading context before matching lines. Places a line containing a group separator (--) between contiguous groups of matches.

As noted in the grep man page, the ouput contains group separators (--) :

2018-04-09T17:19:01.901Z  8 multi frz uuid1 uuid3 uuid2 -
2018-06-03T22:12:38.688Z  8 multi -   uuid1 uuid3 uuid2 -
--
2018-06-28T16:29:01.624Z 10 multi frz uuid1 uuid3 uuid2 -
2018-06-28T17:29:01.624Z 10 multi - uuid1 uuid3 uuid2 -

You can add a third grep to remove them if needed :

grep -A1 frz | grep -vB1 frz | grep -v '^--$'
1
  • 1
    Nice. The regular expressions can be made such that "frz" is taken in the 4th column, but the bones of the solution are strong. Commented Jun 28, 2018 at 20:50
3

I'd like to offer a completely impractical GNU grep approach. Works, but looks nasty.

grep -Pzo "^\S+\s+\S+\s+\S+\s+frz\s+.*\n\S+\s+\S+\s\S+\s+\-\s+.*" input

Example.

$ cat file
2018-04-09T14:15:23.366Z  7 multi -   uuid1 uuid2 uuid3 -
2018-04-09T14:15:23.978Z  8 multi frz   uuid1 uuid3 -        -
2018-04-09T14:29:35.826Z  8 multi frz   uuid1 uuid3 uuid2 -
2018-04-09T17:19:01.901Z  8 multi frz uuid1 uuid3 uuid2 -
2018-06-03T22:12:38.688Z  8 multi -   uuid1 uuid3 uuid2 -
2018-06-28T00:35:54.338Z  9 multi -   uuid1 uuid2 -        -
2018-06-28T00:47:51.679Z  9 multi -   uuid1 uuid2 uuid3 -
2018-06-28T00:47:51.720Z 10 multi -   uuid1 uuid3 -        -
2018-06-28T00:47:58.863Z 10 multi -   uuid1 uuid3 uuid2 -
2018-06-28T16:29:01.624Z 10 multi frz uuid1 uuid3 uuid2 -
2018-06-28T17:29:01.624Z 10 multi - uuid1 uuid3 uuid2 -
$ grep -Pzo "^\S+\s+\S+\s+\S+\s+frz\s+.*\n\S+\s+\S+\s\S+\s+\-\s+.*" file
2018-04-09T17:19:01.901Z  8 multi frz uuid1 uuid3 uuid2 -
2018-06-03T22:12:38.688Z  8 multi -   uuid1 uuid3 uuid2 -
2018-06-28T16:29:01.624Z 10 multi frz uuid1 uuid3 uuid2 -
2018-06-28T17:29:01.624Z 10 multi - uuid1 uuid3 uuid2 -
$ grep -V 2>&1|head -1
grep (GNU grep) 2.20
$
3
  • I get grep: unescaped ^ or $ not supported with -Pz with this. grep version "grep (GNU grep) 2.25" -- I think you need to replace ^ with \n Commented Jun 28, 2018 at 19:02
  • Interesting. v2.20 here, which doesn't have that trouble. Replacing ^ with \n no good on v2.20, results in an unwanted empty line prior to each match.
    – steve
    Commented Jun 28, 2018 at 21:36
  • 1
    I can see on the NEWS file in the grep git repo that they were changing things related to this in versions 2.24 and 2.25 Commented Jun 28, 2018 at 21:54
1

You can try this sed too

sed -E '
  /([^ ]* *){3}frz .*/!d
  $!N
  /(.*\n)([^ ]* *){3}- .*/!D
' infile
4
  • Constrain the N to operate on not last lines, $!N OTW, a last line ending with "frz" in it's 3rd field would get printed too. Commented Jun 29, 2018 at 16:37
  • @RakeshSharma You are right thanks update the answer
    – ctac_
    Commented Jun 29, 2018 at 16:54
  • The first regex is in need of an overhaul, for as things stand now, it will match a line with "frz" in 4th field when it doesn't find in the 3rd but in 4th. You need to ⚓ it to the beginning of pattern space. The .* is superfluous in both the regexes. Commented Jun 29, 2018 at 17:46
  • @RakeshSharma Sorry but I don't understand exactly what you want to say. Yes my answer is not perfect and it's always imaginable to find a way where it fail. If you have a better solution, you can post a answer.
    – ctac_
    Commented Jun 29, 2018 at 18:31

You must log in to answer this question.

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