7

I have a text file filled with a bunch of data. I need to pull out lines that contain specific strings. I accomplished this with awk using the following:

awk '/pattern1|pattern2|pattern3/ {print;}' infile

I then need to put a new line (\n) after ever 3rd line. So it would need to look like this

pattern1
pattern2
pattern3
<new line>
pattern1...

I was able to accomplish this by piping the first command into another awk statement

awk -F '\n' '/pattern1|pattern2|pattern3/ { print; }' infile | awk '{ if ((NR % 3) == 1) printf("\n"); print; }'

I figure that there must be a more efficient way of doing this so I started looking to see how I could combine the two commands together. I tried the following:

awk '/pattern1|pattern2|pattern3/ { if ((NR % 3) ==1 ) printf("\n"); print; }'

I figured this would work but the output is completely unpredictable, sometimes there are 5 lines grouped together, groups of 2 lines, but no lines of 3.

I was thinking that perhaps there was a delimiter issue so I tried playing with the -F option and setting the IFS but neither changed the output.

I figure I am doing something stupid in the way I have tried to combine the pattern match with the if statement but I haven't been able to figure out the combination.

Is what I am trying to do possible in a single awk command? And if so, where am I going wrong?

6

The problem with your attempted solution is that awk's NR is a count of the input records, whereas you want to insert the newline based on the count of the number of output records.

I don't think awk keeps such a count natively, but you could do something like

awk '/pattern1|pattern2|pattern3/ {print; if (++onr%3 == 0) print ""; }' infile

in which we define a new variable onr (for output number of record - the variable name is arbitrary) and increment it every time we match/print the wanted text, then check if that is divisible by 3 and if so print a newline.

  • Hey @steeldriver. What you are saying absolutely makes sense. I read that NR is for input records. But I didn't make the connection with how I was applying the logic. I obviously don't have a full understand. Your solution works! There is one strange thing now; for some reason there are now 2 blank lines between each group of 3. I will see if I can figure out why. Sorry for my ignorance, but what does the "++onr%" do exactly? I think it is doing a count, but I don't recognize the onr. Thank you! – bourne May 28 '14 at 15:35
  • Hmmm I changed the second print to print "" and it got ride of the additional blank line. I think I know why now. It is because in the infile there is a chunk of data, followed by a blank line, then another chunk of data. And with your much cleaner awk statement, that original blank line doesn't get stripped out. – bourne May 28 '14 at 15:40
  • Oops you are right - the extra newline is an error in my code (print adds a newline by default). As you noted, it can be fixed by changing to print "" - or you could use printf "\n". I will edit the answer. – steeldriver May 28 '14 at 15:43
  • thank you! I really appreciate your help. Still have lots to learn. – bourne May 28 '14 at 17:07
0

do I understand correctly, you are trying to invent

awk '/pattern1|pattern2/ {print $1;} /pattern3/ {print $1 "\n"}' infile
  • Hi @vasily-vm. I don't think I am trying to invent. Primarily I am trying to improve my awk code. I need the 3 patterns to be grouped together. The thing is I will end up with multiple groups of 3. After each group of 3 I need to put a blank line due to some formatting restrictions. Cheers – bourne May 28 '14 at 15:38
  • sorry, bad wording :( in fact, I propose to split patterns into 2 group: first one will just copy it, second one - will print additional new line after printing the pattern's matching string example si provided in my answer – vasily-vm May 29 '14 at 13:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.