Command to display nth line before the string is matched.

All,

Is there any way out to display the nth line before the string is matched ???
Eg : If i have a file which has the following contents and if i want to get the
3rd line before the string is matched
a
b
c
d
e
f

if i give the input as f and lines before the match as 3 then it should display then it should give c

i.e in this case its the 3rd line before the string is match.

Specifications : There will be 2 inputs

  1. String to be matched
  2. number

Are there any one line commands to do the same in awk or sed. Need urgent help.

Sounds a little like homework.

If you have gnu (you are on Linux) try grep:

# two parms: $1 string to find $2 lines above
grep -B $2 "$1"  filename

Jim,

Thanks for a quick reply. I am actually using Solaris and Dont think there is a option -B as in Linux. Let me know if you have anyother thought on this..

Thanks.

Use sed and read in (up to) three lines with the "N" subcommand. Use the "D" and "N" subcommands to set up a loop where the next one line is added to the pattern space and the first line of the pattern space is deleted. Once you have encountered your line the first line in the pattern space is the line you searched for.

(You could also use your pattern space solely for the searching and use the hold space as your buffer. In this case use the respective hold-space-manipulation commands instead of setting up the ring buffer with a D-N-loop.

Similar concepts using a buffer of three lines where one line is added "at the bottom" and the first line deleted surrepetitously can be implemented in awk or even shell too. The following implemetation is probably the slowest and least efficient one but the most readable, so it is showing the mechanism best. Note that the "next element" is - because of the ring structure of the buffer - also the third-to-last one:

function pNextElement
{
     (( iCnt=(iCnt+1)%3 ))
}

# main()

chLineBuffer[0]=""
chLineBuffer[1]=""
chLineBuffer[2]=""
iCnt=0

cat file | while read chLineBuffer[$iCnt] ; do
     if [ "${chLineBuffer[$iCnt]}" = "string_to_search" ] ; then
          pNextElement
          print - "The result is ${chLineBuffer[$iCnt]}"
     else
          pNextElement
     fi
done

I hope this helps.

bakunin

How about something like this?

$ cat file.dat
a
b
c
d
e
f

LINE=$(grep -n f file.dat|cut -d: -f1) && LINE=$(($LINE-3)) && head -n $LINE file.dat|tail -1
c

All,

  Thanks for the solutions. i was looking at a one line command and the solution given by SFNYC suits. 

  Bakunin, thanks for the solution as well. I believe the idea of using the sed is good. I shall work on that.. Pour in your thoughts if you find it can be done in much better way.

Thanks to all.