awk command optimization


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting awk command optimization
# 8  
Old 09-13-2014
Strange, this awk script work fine for me.
The case where not work is when a line with more one pattern (only the first pattern find).
In your data file, have you more that one pattern by line ?
# 9  
Old 09-13-2014
Quote:
Originally Posted by SkySmart
Code:
gawk -v sw="error|fail|panic|accepted" 'NR>1 && NR <=128500 {
                                                                                for (w in a)
                                                                                {
                                                                                        if ($0 ~ a[w])
                                                                                                d[a[w]]++
                                                                                }
                                                                }
                                                                BEGIN {
                                                                        c = split(sw,a,"[|]")
                                                                }
                                                                END {
                                                                for (i in a)
                                                                {
                                                                        o = o (a[i]"="(d[a[i]]?d[a[i]]:0)",")
                                                                }
                                                                        sub(",*$","",o)
                                                                        print o
                                                                }' /var/log/treg.test

the above code works majestically when searching for multiple strings in a log.

the problem is, as the log gets bigger (i.e. 5MB), the time it takes to search for all the strings gets longer as well. took 2 seconds to search a 5MB file using this code. had the file been bigger, say 10MB, it would take longer.

so i'm wondering, can this code be optimized at all to make it run faster? maybe if the strings were read from a separate file it would help speed things up??

code runs on linux redhat / ubuntu platforms
No, reading your patterns from a file will not be faster than using split() to extract them from a string!

What is on line 1 and on lines 128501 to the end of your input file. If you can adjust your counters for what I assume is constant data on those lines you can skip two tests that are being performed on every line. (The tests may be fast individually, but performing more than a quarter of a million fast tests adds up.)

If no more than one or your search patterns could appear on a single input line , changing:
Code:
for (w in a) {
        if ($0 ~ a[w])
                d[a[w]]++
}

to:
Code:
for (w in a) {
        if ($0 ~ a[w]) {
                d[a[w]]++
                next
        }
}

would speed things up.

Depending on what percentage of your input lines contain one or more of the search patterns, adding the test:
Code:
if($0 ~ sw) {
        above for loop
}

may speed things up or slow things down. If one of the search patterns appears on every input line, it will slow things down. If none of the search patterns appear on a vast majority of your input lines, it will speed things up. Your mileage will vary depending on your version of awk and your input data.
# 10  
Old 09-13-2014
Quote:
Originally Posted by shamrock
Well you could give this [g]awk a try...
Code:
gawk '{
    for (i=1; i<=NF; i++)
        if ($i ~ "^(error|fail|panic|accepted)$")
            a[$i]++
} END {
    for (i in a) {
        n++
        printf("%s=%s%s", i, a[i], (n < 4 ? ", " : "\n"))
    }
}' file

so this code seems to be doing what i need. however, it doesn't appear to be finding strings that have spaces in them. here's how i'm running it:

Code:
gawk '{
    for (i=1; i<=NF; i++)
        if ($i ~ "(error|fail|panic|open database|accepted)")
            a[$i]++
} END {
    for (i in a) {
        n++
        printf("%s=%s%s", i, a[i], (n < 4 ? ", " : "\n"))
    }
}' file

it finds every other string except the "open database" one. i tried replacing it with "open.*database" and that still didn't work. can this be tweaked to accept strings with spaces?

i also tried:

Code:
gawk '{
    for (i=1; i<=NF; i++)
        if ($i ~ "/error|fail|panic|open database|accepted/")
            a[$i]++
} END {
    for (i in a) {
        n++
        printf("%s=%s%s", i, a[i], (n < 4 ? ", " : "\n"))
    }
}' file


Last edited by SkySmart; 09-13-2014 at 08:00 PM..
# 11  
Old 09-13-2014
Quote:
Originally Posted by SkySmart
so this code seems to be doing what i need. however, it doesn't appear to be finding strings that have spaces in them. here's how i'm running it:

Code:
gawk '{
    for (i=1; i<=NF; i++)
        if ($i ~ "(error|fail|panic|open database|accepted)")
            a[$i]++
} END {
    for (i in a) {
        n++
        printf("%s=%s%s", i, a[i], (n < 4 ? ", " : "\n"))
    }
}' file

it finds every other string except the "open database" one. i tried replacing it with "open.*database" and that still didn't work. can this be tweaked to accept strings with spaces?
... ... ...
Not easily. When your field separator is whitespace characters (the awk default), trying to match a single field that contains one of your field separators is always going to fail. Furthermore, this code will combine your desired patterns with surrounding non-space characters. For instance, with the following contents in file:
Code:
error open
open database
database fail
fail accepted
		if ($i ~ "(error|fail|panic|open database|accepted)")
accepted error
error, fail, panic, open database, accepted

the code:
Code:
gawk '{
	for (i=1; i<=NF; i++)
		if ($i ~ "error|fail|panic|open database|accepted")
			a[$i]++
} END {
	for (i in a) {
		n++
		printf("%s=%s%s", i, a[i], (n < 4 ? ", " : "\n"))
	}
}' file

produces the output:
Code:
error=2, fail=2, fail,=1, error,=1
accepted.=1
accepted=2
panic,=1
"(error|fail|panic|open=1
database|accepted)")=1

Note that the 4 shown in red above controls how many patterns are shown on the 1st line of the output. If all of your patterns only appeared as complete fields (with no punctuation and no additional letter [such as errors or panics]), you would want that number to be the same as the number of patterns you have in your | separated list of patterns.
# 12  
Old 09-14-2014
Quote:
Originally Posted by SkySmart
one question. is the "n < 4" setting a limit of patterns that can be specified?
That was specific to your question as you were looking for 4 patterns and if you want something generic then take out the n...

---------- Post updated at 12:59 PM ---------- Previous update was at 12:47 PM ----------

Quote:
Originally Posted by SkySmart
so this code seems to be doing what i need. however, it doesn't appear to be finding strings that have spaces in them. here's how i'm running it:

Code:
gawk '{
    for (i=1; i<=NF; i++)
        if ($i ~ "(error|fail|panic|open database|accepted)")
            a[$i]++
} END {
    for (i in a) {
        n++
        printf("%s=%s%s", i, a[i], (n < 4 ? ", " : "\n"))
    }
}' file

it finds every other string except the "open database" one. i tried replacing it with "open.*database" and that still didn't work. can this be tweaked to accept strings with spaces?
The gawk above wont work as it splits each line into fields delimited by whitespace...and to find strings or phrases with whitespace you'd have to do something like...
Code:
gawk '{
    a["error"] += gsub("(^| )error( |$)", "&")
    a["fail"] += gsub("(^| )fail( |$)", "&")
    a["panic"] += gsub("(^| )panic( |$)", "&")
    a["accepted"] += gsub("(^| )accepted( |$)", "&")
    a["open database"] += gsub("(^| )open database( |$)", "&")
} END {
    for (i in a)
        printf("%s=%s\n", i, a[i])
}' treg.test

Hope this helps...
This User Gave Thanks to shamrock For This Post:
# 13  
Old 09-14-2014
Quote:
Originally Posted by shamrock
That was specific to your question as you were looking for 4 patterns and if you want something generic then take out the n...

---------- Post updated at 12:59 PM ---------- Previous update was at 12:47 PM ----------


The gawk above wont work as it splits each line into fields delimited by whitespace...and to find strings or phrases with whitespace you'd have to do something like...
Code:
gawk '{
    a["error"] += gsub("(^| )error( |$)", "&")
    a["fail"] += gsub("(^| )fail( |$)", "&")
    a["panic"] += gsub("(^| )panic( |$)", "&")
    a["accepted"] += gsub("(^| )accepted( |$)", "&")
    a["open database"] += gsub("(^| )open database( |$)", "&")
} END {
    for (i in a)
        printf("%s=%s\n", i, a[i])
}' treg.test

Hope this helps...
Yes, it helps a lot!!!

can i pass the strings as an argument instead of hardcoding it in?

Code:
strvar="error|fail|panic|open database|accepted"

# 14  
Old 09-14-2014
I would be interested to see how the performance of these solutions compare with something like:

Code:
egrep -ow "(error|fail|panic|open database|accepted)" treg.test | sort | uniq -c

This User Gave Thanks to Chubler_XL For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. UNIX for Advanced & Expert Users

Need Optimization shell/awk script to aggreagte (sum) for all the columns of Huge data file

Optimization shell/awk script to aggregate (sum) for all the columns of Huge data file File delimiter "|" Need to have Sum of all columns, with column number : aggregation (summation) for each column File not having the header Like below - Column 1 "Total Column 2 : "Total ... ...... (2 Replies)
Discussion started by: kartikirans
2 Replies

2. Shell Programming and Scripting

Code optimization

Hi all I wrote below code: #!/bin/sh R='\033 do you have any idea how to optimize my code ? (to make it shorter eg.) (11 Replies)
Discussion started by: primo102
11 Replies

3. Shell Programming and Scripting

awk command optimization

Hi, I need some help to optimize this piece of code: sqlplus -S $DB_USER/$DB_PWD@$DB_INSTANCE @$PRODUCT_COLL/$SSA_NAME/bin/tools/sql/tablespace.sql | grep -i UNDO_001_COD3 | awk '{printf ";TBS_UNDO_001_COD3"$5"\n"}' sqlplus -S $DB_USER/$DB_PWD@$DB_INSTANCE... (1 Reply)
Discussion started by: abhi1988sri
1 Replies

4. Shell Programming and Scripting

CPU optimization

hi guys , I have 10 scripts suppose 1.sh , 2.sh ,3.sh ,4.sh ......10.sh each takes some time ( for instance 2 minutes to 40 minutes ) my server can run around 3-4 files at a time suppose, 1.sh , 2.sh , 3.sh are running currently now as soon as ANY ONE of the gets finished i... (4 Replies)
Discussion started by: Gl@)!aTor
4 Replies

5. Shell Programming and Scripting

awk command in script gives error while same awk command at prompt runs fine: Why?

Hello all, Here is what my bash script does: sums number columns, saves the tot in new column, outputs if tot >= threshold val: > cat getnon0file.sh #!/bin/bash this="getnon0file.sh" USAGE=$this" InFile="xyz.38" Min="0.05" # awk '{sum=0; for(n=2; n<=NF; n++){sum+=$n};... (4 Replies)
Discussion started by: catalys
4 Replies

6. Shell Programming and Scripting

Awk script gsub optimization

I have created Shell script with below awk code for replacing special characters from input file. Source file has 6 mn records. This script was able to handle 2 mn records in 1 hr. This is very slow speed and we need to optimise our processing. Can any Guru help me for optimization... (6 Replies)
Discussion started by: Akshay
6 Replies

7. Shell Programming and Scripting

sed optimization

I have a process using the following series of sed commands that works pretty well. sed -e 1,1d $file |sed 1i\\"EHLO Broadridge.com" |sed 2i\\"MAIL FROM:${eaddr}"|sed 3i\\"RCPT TO:${eaddr}"|sed 4i\\"DATA"|sed 5s/.FROM/FROM:/|sed 6s/.TO/TO:/|sed 7,7d|sed s/.ENDDATA/./|sed s/.ENDARRAY// >temp/$file... (1 Reply)
Discussion started by: njaiswal
1 Replies

8. Shell Programming and Scripting

AWK optimization

Hello, Do you have any tips on how to optimize the AWK that gets the lines in the log between these XML tags? se2|6|<ns1:accountInfoRequest xmlns:ns1="http://www.123.com/123/ se2|6|etc2"> .... <some other tags> se2|6|</ns1:acc se2|6|ountInfoRequest> The AWK I'm using to get this... (2 Replies)
Discussion started by: majormark
2 Replies

9. Shell Programming and Scripting

script optimization

:o Hi, I am writing a script in which at some time, I need to get the process id of a special process and kill it... I am getting the PID as follows... ps -ef | grep $PKMS/scripts | grep -v grep | awk '{print $2 }'can we optimize it more further since my script already doing lot of other... (3 Replies)
Discussion started by: vivek.gkp
3 Replies
Login or Register to Ask a Question