0

While working on a HP UX storage migration project, I found an awk statement as following

ioscan -funNCdisk | \
awk '{a[NR]=$0} $0~s {f[NR]++} END {for (j=1;j<=NR;j++) if (f[j]) for (i=j+C;i<=j+C;i++) \
print a[i]}' C=1 s="NetApp"

It appears it prints out the lines that match "NetApp" and some more lines related to that keyword.

Could anyone help me understand what this statement means?

Thank you

Kusalananda
  • 14,885
  • 3
  • 41
  • 52
Insan Kim
  • 1
  • 1
  • If you want to learn `awk`, there are some useful links: http://polymer.bu.edu/~fding/sedawk/index.htm http://www.gnu.org/software/gawk/manual/gawk.html http://www.staff.science.uu.nl/~oostr102/docs/nawk/nawk_toc.html – Jdamian Jun 22 '16 at 07:49

2 Answers2

2

Let's break out that awk script into a file by itself and call that file script.awk:

#!/usr/bin/awk -f

BEGIN   { C = 1; s = "pants" }
        { a[NR] = $0 }
$0 ~ s  { f[NR]++ }
END     {
    for (j = 1; j <= NR; j++)
        if (f[j])
            for (i = j + C; i <= j + C; i++)
                print a[i]
}
  1. I added the initialization of the variables s and C in a BEGIN block, just for my own convenience while testing. Your script takes these from the command line.

  2. Add current line last in array a.

  3. If the line contains the string s (tested as regular expression), increment array f at index corresponding to current line (this is the same as f[NR] = 1 in this case).

  4. At end of input: Loop through all stored lines, and if we've flagged the line in the f array print the stored lines, starting at the flagged line plus C and continuing to, uhh, no, just print that single line (bug here?).

Our script will therefore print every line that comes after any line matching the regular expression s.

Testing it:

$ cat data.in
Hello world!
My pants
are on fire!
No, hold on,
Those are not *my* pants.
Phew!

$ chmod +x script.awk

$ ./script.awk data.in
are on fire!
Phew!

So, in your case (replace "pants" with "NetApp" here), it's virtually identical to (using GNU sed)

sed -n '/pants/,+1p' data.in | grep -v 'pants'

or

grep -A1 'pants' data.in | grep -E -v 'pants|-'

Personal note: This is why I hate so-called "one-liners". They are ugly, nobody understands them, and they are totally unmaintainable. Please, please, put complex tasks in a scripts, write it cleanly and with comments, and use that as your "one-liner".

EDIT: After some thinking, I realized that thise script probably tries to implement grep -Cnum re for num = C and re = s (to get C lines of context), but it gets the loop indices wrong in the inner loop (should be i = j - C; i <= j + C).

Kusalananda
  • 14,885
  • 3
  • 41
  • 52
0

Thank you Kusalananda:) Now my curiosity is get released! You're right the range for this loop was originally designed to be from j-c to j+c but somehow modified, probably someone intended to just find one row, not several rows.

Insan Kim
  • 1
  • 1