Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Print fields between two delimiters 1

Status
Not open for further replies.

AnotherAlan

Technical User
Feb 10, 2006
362
GB
Hi All,

Just a quick puzzle really as I have found a suitable workaround, but I was attempting to print the fields from the below example loglines from the word AFTER to the numerals after the word took;

i.e. AFTER Initial lock of quote took 13
AFTER getData for 46681 took 0

2011-05-17 [[ACTIVE] ExecuteThread: '186' for queue: 'weblogic.kernel.Default (self-tuning)'] INFO QuoteServiceImpl - AFTER Initial lock of quote took 13 ms for quote 4
2011-05-17 [[ACTIVE] ExecuteThread: '186' for queue: 'weblogic.kernel.Default (self-tuning)'] INFO QuoteServiceImpl - AFTER getData for 46681 took 0 ms for quote 4

Although I could get the field number for AFTER using a for loop I couldn't work out how to put an end delimiter to it.

Anyway, I got what I needed by using awk and sed;
nawk -F- '/AFTER/ {print $5}' | sed s'/ms.*//g'
but was interested if there was an Awk solution.

Thanks
 
Hi

Code:
nawk -F- '/AFTER/ {sub(/ms.*/,"",$5); print $5}'
Tested with [tt]gawk[/tt] and [tt]mawk[/tt].

( I heard that some old AWK implementations were unable to use [tt]sub()[/tt] directly on the fields. For those you ha(d|ve) to put [tt]$5[/tt] in a variable then [tt]sub()[/tt] that. )

Feherke.
 
Hi Feherke, thanks for the speedy reply.

May I ask another, just for my learning benefit. Feel free to ignore it of course, having already provided an answer ;-)

Using the same examples, if I wanted to print just fields between "AFTER" and "took" and then the numerals after "took"; bearing in mind that the field placings can be completely variable

i.e. Initial lock of quote 13
getData for 46681 0

Can this be easily achieved with Awk?

Many Thanks
 
Hi

I am sure you can [tt]sub()[/tt] out the undesired words yourself, so I would bring another approach into your attention - use the undesired words as field separators :
Code:
awk -F ' (AFTER|took|ms) ' 'NF==4{print$2,$3}'

[gray]# or[/gray]

awk -F ' AFTER | took | ms ' 'NF==4{print$2,$3}'
Tested with [tt]gawk[/tt] and [tt]mawk[/tt].

Note that using more complex regular expression as field separator can slow down the processing.


Feherke.
 
That is cunning and very clever, thanks Feherke. If I could award another star I would.
A lesson in thinking around the problem rather than just bulldozing my way in with complexity.

Appreciate the guidance as always.
Alan
 
Hi

Partially to my relaxation, two more alternative approaches, both [tt]gawk[/tt]-specific :
Code:
awk 'match($0,/AFTER (.+) took (.+) ms/,a){print a[1],a[2]}'

[gray]# or[/gray]

awk 'match($0,/AFTER (.+) took ([[:digit:]]+)/,a){print a[1],a[2]}'

awk '/AFTER/{print gensub(/.* AFTER (.+) took (.+) ms .*/,"[i]1 [/i]2","")}'

[gray]# or[/gray]

awk '/AFTER/{print gensub(/.* AFTER (.+) took ([[:digit:]]+) .*/,"[i]1 [/i]2","")}'
Tested with [tt]gawk[/tt].

[tt]gensub()[/tt] is [tt]gawk[/tt] extension. But [tt]match()[/tt] is POSIX, only its 3[sup]rd[/sup] parameter is not standard, it may be present in [tt]nawk[/tt] too.


Feherke.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top