1

To print multiple(2) lines following the pattern using awk:

I have found somewhere the following solution

$ awk '/Linux/{x=NR+2}(NR<=x){print}' file
Linux
Solaris
Aix

I am trying to understand the syntax

Generally awk syntax is

awk 'pattern{action}' file

Here we find

pattern = /Linux/
action = {x=NR+2}

then what is (NR<=x){print}

Solution:

My understaning of c-like syntax for this is:

While read (file,line)
{
  if (line ~ '/pattern/') then
  {
    x= NR+2
  }
  if (NR <= x)
   {
     print
   {
}

for NR=1 and if (line ~ '/pattern/') then x is set to NR+2 eg(1+2 =3). This value will not be reset till the process is over. SO when the next line is read and !(line ~ '/pattern/') then x is still 3, (NR (2) <= 3) is true so it prints the next line Thanks to @Edmorton for the undestating

Santhosh
  • 9,965
  • 20
  • 103
  • 243
  • I assume that you can reduce the syntax to the following: `awk '/Linux/{x=NR+2} NR<=x' file` – Cyrus Apr 15 '19 at 19:22
  • [awk tutorial](http://grymoire.com/Unix/Awk.html) will explain built in variables like `NR`, etc. Good luck. – shellter Apr 15 '19 at 20:41
  • I mean generally i found `awk '/linux/{x=NR+2; NR <=x; print}`. `patter{execution code}`. Also i dont understant what is the point of `NR <=x` if `x = NR+2`. Also how does this print 2 lines after the match, if this is executed only once – Santhosh Apr 16 '19 at 02:16
  • I am trying to understand how things flow. First it finds the pattern match and stores in $0, then how it loops further without any `for loop` here – Santhosh Apr 16 '19 at 03:01
  • @EdMorton can you also explain the c like syntax for my question What i undestand is `while read (file,line) {if (line ~ '/Linux/') then { x = NR + 2; print}}` I dont understand how (NR<=x) work – Santhosh Apr 16 '19 at 13:43
  • great. So basically till the time it finds `line` again it x will be NR+2, rather than getting reset. THankyou – Santhosh Apr 16 '19 at 13:58

2 Answers2

0

your script has two blocks

$ awk '/Linux/ {x=NR+2}
       NR<=x   {print}' file

first block sets the variable x, second uses to print the lines. Note that you can drop {print}, since it's the default action.

karakfa
  • 66,216
  • 7
  • 41
  • 56
  • But second block needs to be inside {} (braces). I mean generally i found `awk '/linux/{x=NR+2; NR <=x; print}`. Also i dont understant what is the point of `NR <=x` if `x = NR+2` – Santhosh Apr 16 '19 at 02:14
  • No, two blocks are independent from each other. – karakfa Apr 16 '19 at 14:10
0

FWIW I wouldn't write the code you're asking about, instead I'd write:

awk '/Linux/{c=3} c&&c--' file

See example "g" at https://stackoverflow.com/a/17914105/1745001.

Having said that, your original code in C-like syntax would be:

NR=0
x=0
While read (file,line)
{
  NR++
  if (line ~ "Linux") {
    x = NR+2
  }
  if (NR <= x) {
    print
  }
}

Btw, I know it's frequently mis-used but don't use the word "pattern" in your software as it's highly ambiguous - use string or regexp or condition (or in shell but not awk, sed, grep, etc. and only where appropriate "globbing pattern"), whichever it is you really mean.

For example you wrote that awk syntax is:

awk 'pattern{action}' file

No. Or maybe, depending on what you think "pattern" means! Despite what many books, tutorials, etc. say so as to remove any ambiguity you should simply think of awk syntax as:

awk 'condition{action}' file

where condition can be any of:

  1. a key word like BEGIN or END
  2. an arithmetic expression like var < 7 or NF or 1
  3. a regexp comparison like $0 ~ "foo" or $0 ~ /foo/ or /foo/ or $0 ~ var or match($0,/foo/)
  4. a string comparison like $0 == "foo" or index($0,"foo")
  5. nothing at all in which case it's assumed to be true when there's an associated action block.

and probably other things I'm forgetting to list.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185