Combine awk statement into one

awk '{a[NR]=$0} END {while (NR) print a[NR--]}' mail.log | awk '/Feb  2/ {print ;exit;}'

first, can this code be combined into one?

what i want this code to do is output every single line it finds up until the last occurrence of "Feb 2".

right now, this code simply outputs one line, and aborts. but i want it to output all the lines it finds up until the very last occurrence of "Feb 2".

It looks like your current script is trying to print lines in reverse order. Assuming that what you want to do is print lines from mail.log from line 1 through the last line that contains Feb 2 (and print nothing if that string does not appear in the input file), you could try something like:

awk '{a[NR]=$0}
/Feb  2/{last=NR}
END {for(i=1;i<=last;i++)print a}' mail.log

Since you didn't supply any sample input or desired output, this is untested. But, if I understood your requirements correctly, it should be close to what you need as long as you have room to read the entire file into memory.

As always, if you're running this on a Solaris/SunOS system, change awk to /usr/xpg4/bin/awk , /usr/xpg6/bin/awk , or nawk .

1 Like

what i want to do is print the file in reverse order and abort after the very last line containing the string i specified is found.

Reversing the order and talking about the last line matched creates an ambiguity. Making the wild assumption that you want to print the end of the file from the last line in the file that contains the pattern to the end of the file with the output printed in reverse order you should just need to change the last line of the script I suggested to:

END {if(last)for(i=NR;i>=last;i--)print a}' mail.log

Again, with no sample input and expected output, this is untested.

1 Like

Combining your (skysmart's) approach with Don Cragun's, try

awk '{a[NR]=$0} /Feb  2/ {last=NR} END {while (NR >= last) print a[NR--]}' file
1 Like

The difference between these two approaches is that if Feb 2 is not found in the file, my script will print nothing while RudiC's script will print the entire file in reverse order. From the discussion in this thread, I don't know which outcome is preferred.

both of these commands worked great.

however, just one thing. it appears the awk code aborts immediately after the first entry containing "Feb 2" is found. i want it to abort when the last entry is found.

so, it should keep going up until the "Feb 2" string changes to something else.

First or last in a reversed file - my head starts spinning. How about posting in- and output samples, connecting them with some logic description and pointing to the one "Feb 2" that you want?

This is ridiculous.

In addition to what RudiC has already said...

What do you mean by abort? (You do understand that the entire input file has to be read, don't you?) Are you saying you want to process to terminate as the result of a SIGABRT signal instead of terminating with an exit 0?

Explain what should happen in the corner cases. (Such as if the target string is not found.)

i apologize if i wasn't clear.

when i said abort, i meant terminating with an exit code. my use of the word abort seems to have derailed this completely and that is my fault. again, my apologies.

say the content of the file is this:

Feb  1 a jakfif 
Feb  1 nahit 
Feb  2 a jakf
Feb  2 a bcaa
Feb  2 a bc
Feb  3 cna f
Feb  3 jaf af
Feb  4 uiaf aj
Feb  6 whatitoa

the code you supplied is doing this:

feb  6 whatitoa
Feb  4 uiaf aj
Feb  3 jaf af
Feb  3 cna f
Feb  2 a bc

notice how it stops at the first occurrence of the "Feb 2" string.

what i want it do is this:

Feb  6 whatitoa
Feb  4 uiaf aj
Feb  3 jaf af
Feb  3 cna f
Feb  2 a bc
Feb  2 a bcaa
Feb  2 a jakf

---------- Post updated at 09:39 PM ---------- Previous update was at 09:37 PM ----------

my apologies for the confusion.

So you wanted the last occurrence of you pattern in the REVERSED file; not the last occurrence in the file. Try:

awk '
{	a[NR] = $0
}
!last && /Feb  2/{
	last = NR
}
END {	while(NR >= last)
		print a[NR--]
}' mail.log

You still refuse to answer the question about what should happen if the pattern you're looking for doesn't appear at all, so if I guessed wrong again about what you want in that case, you're on your own to fix it.

And, I'll repeat the usual warning... If you want to try this on a Solaris/SunOS system, change awk to /usr/xpg4/bin/awk , /usr/xpg6/bin/awk , or nawk .

1 Like

i will take heed of your warning.

if the pattern is not found, i'm totally ok with the code not showing anything at all.

btw, the log format is in the typical syslog format.

I'm glad that you're OK with the code not showing anything. Unfortunately, if your pattern is not found that code prints the entire file backwards and then prints an empty line.

So why is a file in the typical syslog format named mail.log ?