1

I know that I can grep lines above and below a certain pattern, such as this.
Now I have a problem, I want to grep a line before a certain pattern, but I don't know how far it is, such as:

Time 00:00:01
kkk
lll
aaa
...
Time 00:00:03
kkk
kkk
kkk
lll
lll
aaa
aaa
...
Time 00:00:04
kkk
lll
...

My target pattern is aaa, and the other pattern is "Time xx:xx:xx" and I want the output like this

Time 00:00:01
aaa
Time 00:00:03
aaa
aaa

or

Time 00:00:01
aaa
Time 00:00:03
aaa
Time 00:00:03
aaa

How can I do this?

Community
  • 1
  • 1
sflee
  • 1,659
  • 5
  • 32
  • 63

4 Answers4

4

For your exact output

awk '/^Time/{a=$0}/aaa/{print a"\n"$0}' file

Time 00:00:01
aaa
Time 00:00:03
aaa
Time 00:00:03
aaa

or

awk '/^Time/{a=$0;x=0}/aaa/{print (x++?"":a"\n") $0}' file

Time 00:00:01
aaa
Time 00:00:03
aaa
aaa
3

You Can use the following:

(Time[^\n]*|aaa)

https://regex101.com/r/cY8jN7/2

The same thing for use in grep:

Time[^\n]*|aaa

EDIT: This regex will replace everything except for what you need, so the output is correct:

Time[^\n]*\n((?:(?!Time|aaa)[^\n]*(\n|$))*(?=Time|$))|(?<=\n)(?!Time|aaa)[^\n]+\n

https://regex101.com/r/xP1hT0/1

SanD
  • 839
  • 1
  • 11
  • 31
  • 3
    Won't this also print times don't have aaa ? –  May 07 '15 at 10:14
  • How would you use the new one ? `grep -P 'Time[^\n]*\n((?:(?!Time|aaa)[^\n]*(\n|$))*(?=Time|$))|(?<=\n)(?!Time|aaa)[^\n]+\n'` returns nothing. –  May 07 '15 at 10:55
  • Nvm, grep can only match on single lines, so multiline regexs will not work, although the regex is valid for something that does :). –  May 07 '15 at 10:59
2

Here is a way to do it in Perl:

perl -ane '$t=$_ if /Time/; print $t,$_ if /aaa/' file
Toto
  • 89,455
  • 62
  • 89
  • 125
0

It's real simple with grep:

$ grep -E 'Time |aaa' file

Matcher Selection

-E, --extended-regexp Interpret PATTERN as an extended regular expression (ERE, see below). (-E is specified by POSIX.)