yuzhen
yuzhen

Reputation: 127

extract lines between two same delimiters ( multi instances delimiters)

What I want is from the first occurrence of the delimiter to the last occurrence of the same delimiter,including everything between them,the delimiter may appear multi-times in a log file. enter image description here

sample.log

[T=iaaaaaaaaa134]:SampleClass9: 
[T=iaaaaaaaaa134]:SampleClass7: 
[T=iaaaaaaaaa134]:SampleClass3: 
[T=iaaaaaaaaa134]:SampleClass1: 
[T=i8732jddcd234]:SampleClass1: 
[T=i8732jddcd234]:SampleClass2: 
[T=i8732jddcd234]:SampleClass3: 
[T=i8732jddcd234]:SampleClass4: 
Exception:NullPointerException:
    sampte 1
    sampte 1
    sampte 1
    sampte 1
    sampte 1
    
[T=i8732jddcd234]:SampleClass00: 
[T=i8732jddcd234]:SampleClass00: 
[T=i8732jddcd234]:SampleClass00: 
[T=i8732jddcd234]:SampleClass00: 
[T=i8732jddcd234]:SampleClass00: 
Exception:NullPointerException2:
    sampte 2
    sampte 2
    sampte 2
    sampte 2
    sampte 2
[T=i8732jddcd234]:SampleClass12: 
[T=i8732jddcd234]:SampleClass32: 
[T=i8732jddcd234]:SampleClass22: 
[T=2eeeeeeeee234]:SampleClass32: 
[T=2eeeeeeeee234]:SampleClass82: 
[T=2eeeeeeeee234]:SampleClass22: 
[T=2eeeeeeeee234]:SampleClass22: 

for example: I want to extract the lines starting from the first occurrence of i8732jddcd234 (the delimiter) to the latest occurrence of i8732jddcd234 and everything between them. possibly with awk, sed, grep linux command.because this is a log file on linux server. I tried with

awk /'i8732jddcd234','i8732jddcd234'/ test.log

of course, it won't work

Upvotes: 1

Views: 434

Answers (4)

potong
potong

Reputation: 58401

This might work for you (GNU sed):

sed '/i8732jddcd234/!d;:a;n;:b;//ba;$d;N;bb' file

Delete all lines till there is one containing i8732jddcd234. Print the line containing i8732jddcd234 and then check to see if the following line does too and if so repeat. Otherwise, gather up the lines until the next occurrence of i8732jddcd234 or the end-of-file, in which case the accumulated lines can be deleted.

Upvotes: 0

7 Reeds
7 Reeds

Reputation: 2539

shell only...

    #!/bin/bash

    fileLength=`wc -l dat | cut -d' ' -f1`

    firstMatch=0
    lastMatch=0

    for i in `grep -n i8732jddcd234 dat | cut -d: -f1`; do
        if [ $firstMatch == 0 ] ; then
            firstMatch=$i
        else
            lastMatch=$i
        fi
    done

    diff=$(( lastMatch - firstMatch ))
    topOfMatch=$(( fileLength - firstMatch ))

    tail --lines=$topOfMatch dat | head --lines=$diff

Upvotes: -1

RavinderSingh13
RavinderSingh13

Reputation: 133508

Following awk may help you on same.

awk '/i8732jddcd234/{if(!first){first=FNR};end=FNR} {a[FNR]=$0} END{for(i=first;i<=end;i++){print a[i]}}'  Input_file

Adding a non-one liner form of solution too now.

awk '
/i8732jddcd234/ {
   if (!first) {
      first = FNR
   }
   end = FNR
}
{
   a[FNR] = $0
}
END {
  for(i = first; i <= end; i++) {
     print a[i]
  }
}'  Input_file

Upvotes: 2

glenn jackman
glenn jackman

Reputation: 246807

last=$(nl sample.log | tac | awk '/i8732jddcd234/ {print $1; exit}')
sed -n "/i8732jddcd234/,${last}p" sample.log

or, with awk taking 2 passes through the file:

awk -v code=i8732jddcd234 '
    NR == FNR {
        if ($0 ~ code) {
            if (!first) first=FNR
            last=FNR
        }
        next
    } 
    first <= FNR && FNR <= last
' sample.log sample.log

Upvotes: 1

Related Questions