user115079
user115079

Reputation: 711

get last occuerrence of a line with 2 specific words in linux

I have a text file ( basically a log file) in linux and i have 2 words (alpha, beta).

Now i trying to to search these two words in one line and then print that line and next 15 lines in a temp file. there would be many lines with alpha and beta But I need only last occurrence with "alpha" and "beta" and next 15 lines.

I'll be thankful if you also tell me command in case number of words increase, like 3 or 4 word to search on same line, alpha, beta, gamma

Upvotes: 4

Views: 3210

Answers (6)

potong
potong

Reputation: 58430

This might work for you (GNU sed):

sed '/alpha.*beta\|beta.*alpha/,+15{//{h;d};H};$!d;g;/^$/d' file

or this (all sed's):

sed '/alpha.*beta\|beta.*alpha/{:a;$bb;N;s/\n/&/15;tb;ba;:b;$q;x};$!d;g;/^$/d' file

With two words the regexp /alpha.*beta\|beta.*alpha/ is acceptable, but from there on it gets more tricky to remember all the different combinations. A better way is to list the words as separate regexps at any point bailing out if the line does not contain the current regexp:

sed '/alpha/!bc;/beta/!bc;/gamma/!bc;/delta/!bc;:a;$bb;N;s/\n/&/15;tb;ba;:b;$q;x;d;:c;$!d;g;/^$/d' file

Upvotes: 1

Gilles Quénot
Gilles Quénot

Reputation: 185161

See the following code :

awk '
    {
        file[NR]=$0
    }
    END{
        for (i=NR; i>0; i--) {
            if (file[i] ~ /^alpha, beta/)  {
                for (j=i; j<=i+15; j++) {
                    print file[j]
                }
                exit
            }
        }
    }
' FILE

The algorithm is :

  • for each lines of the file, we feed and array with the current line number as key
  • at the end of the file, we search for the first occurrence of "alpha, beta" in reversed order
  • when the line match, we print this and go in ASC orderto print each values while the array key can be incremented 15 times

Upvotes: 0

user unknown
user unknown

Reputation: 36229

You can use sed too:

sed -n '/alpha.*beta|beta.*alpha/,+15p' file | tail -n 16

Upvotes: 0

frankc
frankc

Reputation: 11473

OmnipotentEntity's is definitely the way to go as long as you stick to 2 words per line. However, it doesn't really scale well beyond that because of the combinatorial explosion in the regex. If you need to match 4 or 5 words in a line, I think something like the below will work without adjustment (i have only tested this partially):


#!/bin/bash 

context=15
file=$1
shift

cmd="cat -n $file"
for s in $@
do
   cmd="$cmd | grep $s"
done

begin=$(eval $cmd | tail -1 | cut -f1)
(( end=$begin + $context ))

sed -n $begin,${end}p $file

The idea is that we attach line numbers to the input file and then build up a series of grep filters. We extract the line number of the last line that passes all the filters and use sed to print out the required range.

Upvotes: 1

OmnipotentEntity
OmnipotentEntity

Reputation: 17131

Your wording was a bit ambiguous, did you want a line with both alpha AND beta or alpha OR beta. If the first:

grep -EA15 'alpha.*beta|beta.*alpha' | tail -16

if the second:

grep -wA15 'alpha|beta' | tail -16

Upvotes: 5

paulsm4
paulsm4

Reputation: 121659

to get the last occurrence of a specific word: "tail"

grep myword myfile.txt| tail -1

For multiple words,

grep -w 'word1|word2' myfile.txt| tail -1

For the last 15 instances of either word,

grep -w 'word1|word2' myfile.txt| tail -15

for more complex scenarios: "sed" or "awk".

Upvotes: -2

Related Questions