?
Solved

Using sed to match a pattern and then return the matched line as well as select lines above it.

Posted on 2003-03-25
13
Medium Priority
?
481 Views
Last Modified: 2013-12-26
Hello, I would like to use sed to search a file for a pattern (word) and then return the line containing that word, as well as the previous 3 lines.

For example, below is my sample file:

Apples are red
Oranges are orange
Pears are green
Bananas are yellow
Turnips are purple
Potatoes are brown

I would like to now search for the work Turnips and the command return the line containing Turnips as well as the previous 3 lines.

So, my output would look like below:

Oranges are orange
Pears are green
Bananas are yellow
Turnips are purple

I have searched sed websites and the closest I can come to the commanded needed is below. But, the below command excludes the line containing the match and I want the command to not only print the previous 4 lines, but also print the line containing the pattern.

#Print the line immediately after a regexp, but not the line
#Containing the regexp
 sed -n '/regexp/{n;p;}'

1.     So I created a sample file (below):

ibm05:/home/root (707)#cat sample_file    
Apples are red
Oranges are orange
Pears are green
Bananas are yellow
Turnips are purple
Potatoes are brown

2.     Then I modified the above command and here is what I get:

ibm05:/home/root (710)#sed -n '/Bananas/{g;1!p;};h' ./sample_file

ibm05:/home/root (711)#

All I get is a blank line. Any help that can be provided will be much appreciated, thanks.
0
Comment
Question by:shanetexas
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 3
  • +3
13 Comments
 
LVL 9

Expert Comment

by:HamdyHassan
ID: 8204987
is this should be in sed ?
Is this homework ?
0
 

Author Comment

by:shanetexas
ID: 8205251
No. I'm trying to create a report for my work out of a large output file. Is there another was to accomplish this other than sed?
0
 
LVL 9

Expert Comment

by:HamdyHassan
ID: 8205594
yes using perl script

---------------------
source code
---------------------

#!/usr/bin/perl

#----------------------
# Define input file
#----------------------
$sourceFile="ss.txt";

#---------------------------------------------------
# Define output files
#---------------------------------------------------
$DATAFile="ss.out";

#----------------------
# Create File Handlers
#----------------------
open(IN,"$sourceFile");
open(OUTA,">$DATAFile");

$l1="";
$l2="";
$l3="";

while ($myline=<IN>){
   if ($myline =~ /Potatoes/)
   {
     print OUTA $l3 ;
     print OUTA $l2 ;
     print OUTA $l1 ;
     print OUTA $myline ;
   }
   $l3=$l2;
   $l2=$l1;
   $l1=$myline;
}
close(IN);
close(OUTA);


-------------
input file
-------------
2733 bin/ee> cat ss.txt
Apples are red
Oranges are orange
Pears are green
Bananas are yellow
Turnips are purple
Potatoes are brown


-------------
output file
-------------
2734 bin/ee> cat ss.out
Pears are green
Bananas are yellow
Turnips are purple
Potatoes are brown
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 

Author Comment

by:shanetexas
ID: 8205803
Is there a less complex way with sed?
0
 
LVL 9

Expert Comment

by:HamdyHassan
ID: 8205910
It should be easy also with AWK
0
 

Author Comment

by:shanetexas
ID: 8206035
How would I do it with awk?
0
 
LVL 5

Expert Comment

by:ecw
ID: 8206424
Trivially in awk ...

awk -v pattern="$pattern" 'BEGIN {
            prev1 = prev2 = prev3 = "";
}
{ if ($0 ~ pattern) print prev1 "\n" prev2 "\n" prev3 "\n" $0;
}
{ prev1 = prev2 ; prev2 = prev3 ; prev3 = $0 }
}' file

There are more elegant methods, but this should suffice, although it might output some spurious blank lines.
0
 

Author Comment

by:shanetexas
ID: 8206656
The awk script provided did not work. Here is the output it produced (I put the awk script into a file names shane2):

tech2:/home/root (695)#shane2          



Apples are red


Apples are red
Oranges are orange

Apples are red
Oranges are orange
Pears are green
Apples are red
Oranges are orange
Pears are green
Bananas are yellow
Oranges are orange
Pears are green
Bananas are yellow
Turnips are purple
Pears are green
Bananas are yellow
Turnips are purple
Potatoes are brown
0
 
LVL 48

Expert Comment

by:Tintin
ID: 8206960
Depends what flavour Unix you have or if you have GNU grep.

If so, then it is simple:

grep -B 3 Turnips sample.txt
0
 
LVL 5

Accepted Solution

by:
ecw earned 300 total points
ID: 8207149
Looks like you're searching for blank pattern, in whch case every line will match.
The gist of the awk script is to put in shell var pattern the word you're searching for.
ie.
 pattern=yellow
and then the awk stuff.

So to turn it into a full script, with a little bit more intelligence,

#!/bin/sh

awk -v pattern="$1"
shift
awk -v pattern="$pattern" 'BEGIN {
 lines[1] = line[2] = line[3] = ""
}
{ if ($0 ~ pattern) {
   if (NR > 3) {
     for (i = 1; i <= 3; ++i) print lines[i];
   } else {
     for (i = 1; i <= NR; ++i) print lines[i];
   }
   print $0;
  }
}
{ line[1] = line[2] ; line[2] = line[3] ; line[3] = $0 }
}' ${1+"$@"}
0
 
LVL 5

Expert Comment

by:ecw
ID: 8207179
whoops, line shouldn't be
 awk -v pattern="$1"
should be
 pattern="$1"
0
 
LVL 3

Expert Comment

by:prady_21
ID: 8222836
Well if the file size isnt too big, then you can try this

#!/usr/bin/perl

$filehandle = "/home/somewhere/some.txt";
open ( FILE, "$filehandle");
@lines =reverse <FILE>;
for $i ( 0 .. $#lines ) {
   if ( $lines[$i] =~ /Turnip/g) {
      @array_line = @lines[$i,$i+1,$i+2,$i+3];
      print "@array_line";
   }
}
exit 0;

0
 
LVL 18

Expert Comment

by:liddler
ID: 9846002
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Answered by ecw

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

liddler
EE Cleanup Volunteer
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
NetCrunch network monitor is a highly extensive platform for network monitoring and alert generation. In this video you'll see a live demo of NetCrunch with most notable features explained in a walk-through manner. You'll also get to know the philos…
Suggested Courses

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question