#!/bin/ksh ## ## SCRIPT: egrep_like_awk_plusminusNlines ## ## in $FEDIR/scripts where $FEDIR=/apps/nns_com/fea ## ############################################################################# ## PURPOSE: Shows $1 lines both above and below lines which contain a match to ## the string(s) in $2. The file being searched is named in $3. ## ## $1 $2 $3 represent the 3 positional arguments to this script. ## ## Like 'egrep', the string argument may be sub-strings separated ## by vertical-bars (|). Hence, the file can actually be searched ## for an OR-match, in any record of the file, to the several ## sub-strings within the string. ## ## Example string: 'fatal|error|fail|warning' ## ## 'awk' is used to find the match and save/print the N lines ## above a match line as well as the N lines following, where N = $1. ## ## This is an 'egrep-like' utility --- except that it shows lines ## around the match lines --- and does this with 'awk', ## because 'egrep' is not capable of showing the nearby lines. ############################################################################# ## CALL FORMAT: ## ## $FEDIR/scripts/egrep_like_awk_plusminusNlines ## ## Can test with ## ./egrep_like_awk_plusminusNlines 3 'tk|tool|DISPLAY' $HOME/test_eegrep ## ./egrep_like_awk_plusminusNlines 2 'tk|tool|DISPLAY' $HOME/test_eegrep ## ./egrep_like_awk_plusminusNlines 1 'tk|tool|DISPLAY' $HOME/test_eegrep ## ./egrep_like_awk_plusminusNlines 0 'tk|tool|DISPLAY' $HOME/test_eegrep ## and ## ./egrep_like_awk_plusminusNlines 6 'tk|tool|DISPLAY' $HOME/test_eegrep ############################################################################# ## CALLED BY: various FEA/CAE/CAD/Viz utility scripts, like ## ## $FEDIR/scripts/ddam_find_f06_errs_bygui ## ############################################################################# ## MAINTENANCE HISTORY: ## Written by : Blaise Montandon 26jul2001 Based on script ## 'grep_3lines_around' ## in $FEDIR/scripts ## which is called by 'grep3' in $FEDIR/scripts. ## Also, see /apps/nns_com/fea/Dscrtest/test_awk_like_egrep ## Last Update: Blaise Montandon 26jul2001 ############################################################################# ############################################################################# ## Check for input item #1. ############################################################################# if test "$1" = "" then echo " INPUT ERROR: Supply an INTEGER (and a string and a filename) to script $0. Input: Example: $0 3 'error|warning|core|dump' /var/adm/SYSLOG Exiting ... " exit fi ############################################################################# ## Check for input item #2. ############################################################################# if test "$2" = "" then echo " INPUT ERROR: Supply a string to script $0. Input: Example: $0 3 'error|warning|core|dump' /var/adm/SYSLOG Exiting ... " exit fi ############################################################################# ## Check for input item #3. ############################################################################# if test "$3" = "" then echo " INPUT ERROR: Supply a filename to script $0. Input: Example: $0 3 'error|warning|core|dump' /var/adm/SYSLOG Exiting ... " exit fi ############################################################################# ## CALL 'awk' -- with an appropriate awk program -- with file $3 as input. ## (Output is simply allowed to go to stdout. The calling utility script ## can direct stdout into an appropriate file.) ############################################################################# ## 'awk' program (AN EXAMPLE) to ## write all lines whose first field is different from the previous one. ## ## $1 != prev { print; prev = $1 } ## NOTE: ## This extended-egrep 'eegrep' script is basically ## a more complex version of this. ############################################################################# ################################################## ## FOR TESTING: ################################################## # TEST="YES" TEST="NO" if test "$TEST" = "YES" then echo " *.......................................................... * Lines in file $3 * that match the '|'-separated sub-strings in '$2' * --- including $1 line(s) above-and-below matches * --- are shown below. *.......................................................... * All lines are preceded by line numbers. * An asterisk (*) before a line-number indicates a match. *.......................................................... " # set -x fi ################################################## ## HERE's the 'awk'. ################################################## awk -v N="$1" -v STRING="$2" \ 'BEGIN { ####################################################### ## Initialize the N "prev" vars to null. ## They are to hold the last N lines read. ####################################################### for ( i = 1 ; i <= N ; i++ ) { prev[i] = "" } ################################################## ## After converting STRING to upper-case, ## split the "STRING" into NS "subSTRING"s -- at ## occurrences of a vertical bar (|). ################################################## STRING=toupper(STRING) NS=split(STRING,subSTRING,"|") ## FOR TESTING: # print NS # print subSTRING[1] # print subSTRING[2] # print subSTRING[3] ################################################### ## "aftcount" holds the integer N,N-1,...,2,1, or 0 ## --- representing the number of lines after the ## last matched line that still need to be printed. ################################################### aftcount = 0 ###################################################### ## "lastprt" holds the line# of the line last printed. ## "lastprt" is reset any time "printf" is called. ###################################################### lastprt = 0 } #END OF BEGIN #START OF BODY { #################################################### ## IF WE HAVE A MATCH, SUSPEND PRINTING ## at N "AFTER-A-MATCH-LINES": ## If there is a new match, reset "aftcount" to zero. ## (We do not want to print a line twice.) ## We will restart aftcount at N after the new match ## line is printed. #################################################### ## We use "Match" to indicate whether there was a ## match to at least one of the subSTRINGs, in the ## current line ($0). Match==1 indicates a match. #################################################### Match = 0 UPPER=toupper($0) for ( i = 1 ; i <= NS ; i++ ) { if ( UPPER ~ subSTRING[i] ) { aftcount = 0 ; Match = 1 } ## FOR TESTING: # print "subSTRING LOOP:: " subSTRING[i] " aftcount: " aftcount " Match: " Match } ## FOR TESTING: # }" $3 # exit ###################################################### ## PRINT ONE OF THE N "AFTER-A-MATCH-LINES": ## If "aftcount" is non-zero, print the current line. ## We had a match up to N lines ago. Decrement "aftcount" ## and save the number of the printed line in "lastprt". ###################################################### if ( aftcount != 0 ) { printf (" %s : %s \n", NR, $0); ## If this is the last of the "aftcount" lines, ## print a blank line. if ( aftcount == 1 ) {print ""} aftcount = aftcount - 1 ; lastprt = NR ## FOR TESTING: # print "aftcount != 0 CHECK:: aftcount: " aftcount " lastprt: " lastprt } ## FOR TESTING: # }" $3 # exit ###################################################### ## IF WE HAVE A MATCH, PRINT N-PREV & CURRENT: ## If there is a match, print the N previous lines ## --- as long as their linenums are greater than ## the last-printed line number. (We do not want ## to print a line twice.) ## ## Then print the current line. Also set "aftcount" ## to N, and save the ## number of the matched-printed line in "lastprt". ###################################################### for ( i = N ; i > 0 ; i-- ) { recnum = NR - i if ( Match == 1 && recnum > lastprt ) { printf (" %s : %s \n", recnum, prev[i]) } ## FOR TESTING: # print "prev[] PRINT-LOOP:: NR= " NR " recnum= " recnum " i= " i # print "prev[] PRINT-LOOP:: lastprt= " lastprt " prev[i]= " prev[i] } if ( Match == 1 ) { printf ("*%s : %s \n", NR, $0); aftcount = N; lastprt = NR ## FOR TESTING: # print "Match == 1 TEST:: aftcount: " aftcount " lastprt: " lastprt } ######################################################## ## Update prev[N], prev[N-1], ... , prev[2], and prev[1] ## before reading the next line. ######################################################## for ( i = N ; i > 1 ; i-- ) { prev[i] = prev[i-1] } prev[1] = $0 #END OF BODY }' $3