ximarin
ximarin

Reputation: 401

grep - show two parts of matching line

I've read through the man page of grep and tried few things, none of them worked, at least not for me.

I want to extract a good readable line while tailing a log. This is a generic line in a log file I want to beautify:

26 Jan 2018 08:32:29,309 [TEXT] (myService-0) long.text.I.dont.care.about.but.is.different.in.every.line: [OTHERTEXT] Text im actually interested in

What I want is this:

26 Jan 2018 08:32:29,309 [TEXT] [OTHERTEXT] Text im actually interested in

I know that with grep -o -e ".*\[TEXT\]" I get the first part, and with grep -o -e "\[OTHERTEXT\].*", I get the second part.

But this is not displayed on one line, also not if I combine it into grep -o -e ".*\[TEXT\]" -e "\[OTHERTEXT\].*"

[TEXT] and [OTHERTEXT] always are there and are my 'separators', so can be used to support extracting the parts I need.

I initially thought I could use grep -o -e "(.*\[TEXT\]).*(\[OTHERTEXT\].*)" and then somehow use the matching groups $1 and $2, but either I don't see it or there is no way to do so.

Is there a way to achieve what I want?

Preferred is using grep (simply because I want to learn more about it), but if that is not possible then awk or sed are fine as well, it just has to be usable with a tail -f.

And I'm also open to other approaches to get to that point, so let me know what ways exist to get there.

Thanks, Tobias

Upvotes: 3

Views: 2494

Answers (5)

James Brown
James Brown

Reputation: 37404

Using awk you could replace everything between ] and [ with ] [:

$ awk 'sub(/\].*\[/,"] [")' file
26 Jan 2018 08:32:29,309 [TEXT] [OTHERTEXT] Text im actually interested in

Upvotes: 1

rools
rools

Reputation: 1675

You probably need sed for doing what you want:

sed -E 's/(.*\[TEXT]).*(\[OTHERTEXT])/\1 \2/' 

But to answer to your question about how to show matches in grep, yes it is possible with the option -o. This option will show only matched parts of the matching line. Nevertheless, if you use

grep -o -e ".*\[TEXT\]" -e "\[OTHERTEXT\].*"

you will get your matched parts but in separate lines.

Another possibility could be to use look-ahead and look-behind expressions, but it cannot work in your case.

Upvotes: 0

Sundeep
Sundeep

Reputation: 23667

you can do that with perl

$ # note that this will print empty lines when no match is found
$ perl -lne 'print /(.*\[TEXT\] ).*(\[OTHERTEXT\].*)/' ip.txt
26 Jan 2018 08:32:29,309 [TEXT] [OTHERTEXT] Text im actually interested in
$ # you can avoid empty lines by checking for match first
$ perl -lne '/(.*\[TEXT\] ).*(\[OTHERTEXT\].*)/ && print $1,$2' ip.txt
26 Jan 2018 08:32:29,309 [TEXT] [OTHERTEXT] Text im actually interested in

since you are processing tail -f output, you might need buffering control, see How to 'grep' a continuous stream? for example

Upvotes: 0

developer
developer

Reputation: 728

pipe your grep into

<your grep> | sed "s/(myService-0).*[OTHERTEXT]/(myService-0)[OTHERTEXT]/"

Upvotes: 0

anubhava
anubhava

Reputation: 785108

You can use sed:

sed -E 's/(\[TEXT]).*(\[OTHERTEXT])/\1 \2/' file.log

26 Jan 2018 08:32:29,309 [TEXT] [OTHERTEXT] Text im actually interested in

This sed matches a pattern between [TEXT] and [OTHERTEXT] and captures them in 2 groups. In replacement it puts those markers back using back-refrences \1 \2

Upvotes: 4

Related Questions