Disclaimer : All the postings on this site are my own and don’t necessarily represent IBM’s positions, strategies or opinions.
 
Many a times while using grep we would want to see few lines either/both before/after the matching lines.

While working on AIX, I have seen the need of options in ‘grep‘ to ‘print certain number of lines before or/and after the matching lines’; And AIX grep command by itself does not support these kind of options.


Let me reiterate the need for such options with an example. Suppose you have a file with contents like this (with three lines per entry depicting the Company, Name and Place of a person .. and there are thousand such entries ) :

(0) root @ test_machine: /
# cat example.txt
Company : DEF
Name : Appu
Place : Bangalore


Company : GHI
Name : Pappu
Place : Kozhikode

” ” ” ” ” ” ” ”

Now you want to get the Name of all the persons working for the Company : GHI. How do you do that ?
You can get that done by awk, sed etc.
I have a written a ksh script using egrep and awk to get the work done. and this works on AIX, and Linux too 🙂

Let me show the usage of the script

(0) root @ test_machine: /
# ./sgrep.sh
Usage:
                sgrep -p <pattern> -f <path-to-file>
                [-b <#lines_before_match> -a <#lines_after_match>]

The options are self-explanatory; with “-p” to be used to specify the pattern to search for in file specfied with “-f” option. “-b” and “-a” are optional and tell the number of lines before and after the match to be displayed.

To search for Name and Place of all the persons working for Company ‘GHI’, the query would look like this :

(0) root @ test_machine: /
# ./sgrep.sh -p GHI -f example.txt -a 2
5:Company : GHI
9:Company : GHI
—————————————

>>>>>> 5 <<<<<<

Company : GHI
Name : Pappu
Place : Kozhikode
>>>>>> 9 <<<<<<

Company : GHI
Name : Kutti
Place : South Balanda

The result above shows the normal egrep output with line_no followed by a red dashed line “——–

What follows is the context-lines of the matching lines; which includes either/both the lines before or after the matched line and each search is separated by “>>>>>> <pattern-matched-line-no> <<<<<<

Until I figure out on how to upload a shell-script in wordpress, here is the entire source-code :

#!/usr/bin/ksh

##################################################################
# Author : Sangeeth Keeriyadath (http://day2dayunix.sangeek.com/)
# Version : 0.1
# This script can be freely distributable and modified as required
###################################################################

usage()
{
    USAGE=”Usage:
        sgrep -p <pattern> -f <path-to-file>
        [-b <#lines_before_match> -a <#lines_after_match>]”

    print -u2 “$USAGE”
    exit 1
}        

while getopts “:p:b:a:f:” OPTION; do
    case $OPTION in
        p) pattern=”$OPTARG” ;;
        b) before=”$OPTARG” ;;
        a) after=”$OPTARG” ;;
        f) file=”$OPTARG” ;;
        *) usage
           ;;
    esac
done

if ([[ -z $pattern ]] || [[ -z $file ]]); then
    usage;
    exit 1;
fi

egrep -n $pattern $file
echo “\033[31m—————————————“;
echo “\033[0m”

if ([[ -z $after ]] && [[ -z $before ]]); then
    exit 0;
fi

for i in egrep -n $pattern $file | cut -f 1 -d:
do
    echo “\033[31m>>>>>> “$i” <<<<<<“;
    echo “\033[0m”
    line_no=print $i;

    if ([[ -n $after ]] && [[ -n $before ]]); then
        l_before=$(expr $line_no – $before);
        l_after=$(expr $line_no + $after);
            awk ‘NR >= ‘$l_before’ && NR <= ‘$l_after $file
    elif ([[ -n $after ]]); then
        l_after=$(expr $line_no + $after);
            awk ‘NR >= ‘$line_no’ && NR <= ‘$l_after $file
    elif ([[ -n $before ]]); then
        l_before=$(expr $line_no – $before);
            awk ‘NR >= ‘$l_before’ && NR <= ‘$line_no $file
    fi
done

 

GNU grep makes this task easier by supporting these flags :

   Context Line Control
       -A NUM, –after-context=NUM
              Print  NUM lines of trailing context after matching lines. 
       -B NUM, –before-context=NUM
              Print NUM lines of leading context before matching lines.
       -C NUM, -NUM, –context=NUM
              Print NUM lines of output context.

So, if you are using GNU grep you won’t need my script 🙂

 

What do you think ?

Set your Twitter account name in your settings to use the TwitterBar Section.
%d bloggers like this: