Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a log file looking somtheing like :

SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-RTP-Trust
                               ^
% Invalid input detected at '^' marker.

SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-Control-Trust
                               ^
% Invalid input detected at '^' marker.

SWEs-elmPCI-A-01(config)#
 policy-map AutoQoS-Police-CiscoPhone
SWEs-elmPCI-A-01(config-pmap)#

Now i have to look for all the lines begining with % symbol between the lines containing hash # and put it into another error log file.

if you consider the above then this should go into error log file.

   SWEs-elmPCI-A-01(config)#
     class AutoQoS-VoIP-RTP-Trust
                                   ^
    % Invalid input detected at '^' marker.

    SWEs-elmPCI-A-01(config)#
     class AutoQoS-VoIP-Control-Trust
                                   ^
    % Invalid input detected at '^' marker.

    SWEs-elmPCI-A-01(config)#
share|improve this question
1  
Are you supposed to include that last line? –  Sukminder Mar 26 '13 at 10:27
    
all the lines containing % between lines with # and # even if it is the last line.all i have to include the lines with # and # and should have all the lines between them if it has got a % at the begining –  munish Mar 26 '13 at 10:34
add comment

2 Answers 2

up vote 1 down vote accepted

Maybe something like:

sed 'H;/#$/!d;s/^/\
/;x;/\n%/!d;s/.//;x;s/.*//;x'

Since you want both the prompt before the error and after the error, that one includes both except for prompts that would otherwise appear both as the prompt after one error and the one before the next error to match your sample output.

It's a lot simpler if we include both prompts regardless of whether errors follow each other or not:

sed 'H;/#$/!d;x;/\n%/!d'

If you wanted only the prompt before the error, that would also be a lot simpler:

sed '/#$/!{H;d;}
     x;/\n%/!d'

Probably the best way to explain those is translate to a more verbose language like perl. In sed, the hold space is like a static variable that is initialised with an empty line, and the pattern space a variable which sed assigns in turn to every line of input. Something like:

$hold_space = "\n";
LINE: while ($pattern_space = <>) {

  <sed commands go here>

  print $pattern_space; # unless -n option is passed
}

The H command translates to:

$hold_space .= $pattern_space;

The d command translates to:

next LINE;

That is stop executing the commands, discard the pattern space and start fresh with the next line of input.

x swaps pattern and hold space:

($pattern_space, $hold_space) = ($hold_space, $pattern_space);

So that last sed command translates to:

$hold_space = "\n";
LINE: while ($pattern_space = <>) {

  if (! ($pattern_space =~ /#$/)) { # anything other than a prompt
    $hold_space .= $pattern_space;
    next LINE;
  }

  ($pattern_space, $hold_space) = ($hold_space, $pattern_space);

  if (! ($pattern_space =~ /\n%/)) {
    next LINE;
  }

  print $pattern_space;
}

Which can be re-written in a more legible fashion as:

LINE: while ($pattern_space = <>) {

  if ($pattern_space =~ /#$/)) {
    if ($hold_space =~ /\n%/)) {
      print $hold_space;
    }
    $hold_space = $pattern_space;
  } else {
    $hold_space .= $pattern_space;
  }
}

Rename $pattern_space to $line and $hold_space to $current_block and it becomes even more legible.

share|improve this answer
    
Thanks a lot @Stephane it works like a charm. it seems very easy for you but i find data exchange between hold space and space bit tricky.i havn't used them much as well.i was wondering if you could explain any one of the examples...-:).Still trying to understand this anyway –  munish Mar 27 '13 at 10:31
add comment

Not sure if this is what you want, but:

#!/bin/bash

awk '
BEGIN {
    err=0
}
/^SWE.*#$/ {
    if (err) {
        printf "%s\n%s", txt, $0
        txt=""
        err=0
    } else {
        txt=$0
    }
    next
}
/^% Invalid/ {
    err=1
    txt=txt "\n" $0
    next
}
{
    txt=txt "\n" $0
}
END {
    print ""
}
' "$1"

Result:

SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-RTP-Trust
                               ^
% Invalid input detected at '^' marker.

SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-Control-Trust
                               ^
% Invalid input detected at '^' marker.

SWEs-elmPCI-A-01(config)#

As an alternative, how I tought it was with extra lines to group:

awk '
BEGIN {
    i = 0
    sep="------------------------------------------------"
}
/^% Invalid/ {
    printf "%s %3d\n%s\n%s\n%s\n",
    sep, ++i, txt, $0, sep
    txt=""
    next
}
/^SWE.*#$/ {

    txt=$0
    next
}
txt != "" {
    txt=txt "\n" $0
}
' "$1"

Result:

------------------------------------------------   1
SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-RTP-Trust
                               ^
% Invalid input detected at '^' marker.
------------------------------------------------
------------------------------------------------   2
SWEs-elmPCI-A-01(config)#
 class AutoQoS-VoIP-Control-Trust
                               ^
% Invalid input detected at '^' marker.
------------------------------------------------
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.