59992

On AIX, grep -B -A -m does not work. Any solution with sed or awk

Question:

I am on AIX system. But grep on AIX does not support -B, -A, -M on AIX system. Are there other solutions like awk or sed which can do the same job?

For example:

str1 str2 str3 str4 str9 str8 str1 str3 str2

I try to run grep str3 -m 1 -B 1 -A 1 to get:

str2 str3 str4

but it does not work on AIX. Is there any solution for sed or awk?

Answer1:

awk 'c&&c--;/str3/{print p;print $0;c=1}{p=$0}' file

Answer2:

You can use a circular buffer which you print when the match is found, followed by the matched line, followed by the additional lines.

#!/usr/bin/awk -f BEGIN { B = 4 # set these values like you would use for grep -B, -A, -m A = 2 m = 3 patt = "999" # set this to your regex i = 0 B++ # the buffer will hold B lines plus one for the match } { a[i] = $0 # accumulate B (+1) lines in a circular buffer i = (i + 1) % B } $0 ~ patt { # if the pattern is found print the contents of the buffer for (j=1; j<=B; j++) { print a[i] i = (i + 1) % B } split("", a) for (i=1; i<=A; i++) { # print the next A lines getline print } if (--m == 0) exit # output m matches then quit print "---" }

A more sophisticated script would accept options and arguments rather than having to edit it to change them.

As a compromise, you could rearrange things a little and pass arguments using AWK's -v option.

Answer3:

By the way, congratulations and +1 for providing sample input and output. You would be surprised how many questions are missing such obvious specifications...

This can be done with ed(1).

so ross$ cat >> cg.ed /str3/-1;.+2p so ross$ ed - cg.txt < cg.ed str2 str3 str4 so ross$

You can make a script out of this that will take the filename and pattern as arguments:

so ross$ cat > cg.sh #!/bin/sh ed - $1 << eof /$2/-1;.+2p eof so ross$ sh cg.sh cg.txt str3 str2 str3 str4 so ross$

Answer4:

I have a 78-line shell script that does the job. I later replaced it with a 114-line Perl script, but normally port GNU grep where I need the facility. The shell script follows - it uses a different nomenclature for the options (AFAIK, it predates the options on GNU grep; it was certainly developed independently of the options in GNU grep).

#!/bin/ksh # # @(#)$Id: old.sgrep.sh,v 1.5 2007/09/15 22:15:43 jleffler Exp $ # # Special grep # Finds a pattern and prints lines either side of the pattern # Line numbers are always produced by ed (substitute for grep), # which allows us to eliminate duplicate lines cleanly. If the # user did not ask for numbers, these are then stripped out. # # BUG: if the pattern occurs in in the first line or two and # the number of lines to go back is larger than the line number, # it fails dismally. set -- `getopt "f:b:hn" "$@"` case $# in 0) echo "Usage: $0 [-hn] [-f x] [-b y] pattern [files]" >&2 exit 1;; esac # Tab required - at least with sed (perl would be different) # But then the whole problem would be different if implemented in Perl. number="'s/^\\([0-9][0-9]*\\) /\\1:/'" filename="'s%^%%'" # No-op for sed f=3 b=3 nflag=no hflag=no while [ $# -gt 0 ] do case $1 in -f) f=$2; shift 2;; -b) b=$2; shift 2;; -n) nflag=yes; shift;; -h) hflag=yes; shift;; --) shift; break;; *) echo "Unknown option $1" >&2 exit 1;; esac done pattern="${1:?'No pattern'}" shift case $# in 0) tmp=${TMPDIR:-/tmp}/`basename $0`.$$ trap "rm -f $tmp ; exit 1" 0 cat - >$tmp set -- $tmp sort="sort -t: -u +0n -1" ;; *) filename="'s%^%'\$file:%" sort="sort -t: -u +1n -2" ;; esac case $nflag in yes) num_remove='s/[0-9][0-9]*://';; no) num_remove='s/^//';; esac case $hflag in yes) fileremove='s%^$file:%%';; no) fileremove='s/^//';; esac for file in $* do echo "g/$pattern/.-${b},.+${f}n" | ed - $file | eval sed -e "$number" -e "$filename" | $sort | eval sed -e "$fileremove" -e "$num_remove" done rm -f $tmp trap 0 exit 0

Answer5:

this little coding will highlight the regexp and works like grep -A -B -m Hope this helps.

Christian Knauer

#!/bin/bash [ $# -lt 2 ] && printf "usage: %s <regex> <file> [[[back]forward]occurrence] \n" "$0" && exit 0 REGEX=$1 FILE=$2 BACK=${3:-1} FORWARD=${4:-1} STOP=${5:-1000000000} awk -v bold=$'\e[1m' -v norm=$'\e[0m' -v back=$BACK -v forward=$FORWARD -v stop=$STOP 'BEGIN {cnt=0} { array[i++]=$0 } END { maxI=++i for (j=0;j<maxI; j++) { if (array[j] ~ /'"${REGEX}"'/) { for (z=back;z>0; z--) { print array[j-z] } printf bold > "/dev/stderr" printf("%s\n", array[j]) printf norm > "/dev/stderr" for (x=1;x<=forward; x++) { print array[j+x] } cnt++ if (cnt == stop) { break } } } } ' "$FILE"

Answer6:

Slightly simplified <a href="https://stackoverflow.com/a/5062981/7551394" rel="nofollow">DigitallRoss' answer</a> that additionally prints ALL matching lines, not only first one matching the str3 pattern:

echo ',g/str3/-1;+2p' | ed - myFile.txt

where

, # read all lines (from first to the very last) g/str3/ # search for `str3` string -1 # take 1 line BEFORE the matching one ;+2 # and also next 2 lines (so 3 lines in total) p # and print them

If you want to print only FIRST occurrence then the command is simpler:

echo '/str3/-1;+2p' | ed - myFile.txt

where

/str3/ # find line matching the `str3` string -1 # take 1 line BEFORE the matching one ;+2 # and also next 2 lines (so 3 lines in total) p # and print them

Recommend

  • Training neural network using particle swarm optimization in matlab
  • PHP Regex Question
  • Escape backslash in XML and split as separate xml node using XSLT
  • Height 100% not working for nested div
  • Get projection limits from Postgis
  • JavaScript: modify prototype of an object's variable?
  • SSH, run process and then ignore the output
  • What am I not getting about foreach loops?
  • When is it better for an assembler to use sign extended relocation like R_X86_64_32S instead of zero
  • Insert a multiline string with arbitrary special characters to a template file in a shell script
  • Select Earliest Order for a set of tests in a daterange SQL
  • How to get boolean property with expression language?
  • R - Combinations of a dataframe with constraints
  • When interface inheritance in Java is useful?
  • Can't connect Entity Framework to local SQL Server Express
  • Sympy: working with equalities manually
  • Yii2: Using Kartik Depdrop Widget?
  • How to determine the CCSID used in CPYFRMIMPF command?
  • How to save dynamically created textboxes and their values
  • php is_file always return false
  • Efficient User-Agent Regex to find Safari in Python
  • Is it possible to get the word under the mouse cursor in a ``?
  • pip in virtualenv gets ConnectTimeoutError
  • Run multiple queries from 1 SQL file showing result in multiple tables
  • Installed module is empty
  • Knitr HTML Loop - Some HTML output, some R output
  • Why joiner is not used after Sequence generator or Update statergy
  • Exception on Android 4.0 `android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode)`
  • File not found error Google Drive API
  • How to get Windows thread pool to call class member function?
  • Bitwise OR returns boolean when one of operands is nil
  • Is it possible to post an object from jquery to bottle.py?
  • XCode 8, some methods disappeared ? ex: layoutAttributesClass() -> AnyClass
  • Easiest way to encapsulate a HTML5 webpage into an android app?
  • Busy indicator not showing up in wpf window [duplicate]
  • costura.fody for a dll that references another dll
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Conditional In-Line CSS for IE and Others?