When strictly processing flat files, very often awk is faster than perl, depending on many factors.
One might suggest that you try a different version of awk on the platform you are using.
With an example input file:
sunt2000/user777$ cat ./test.in
recordstart
val1 1
val2 2
val3 4
recordstart
val1 5
val2 6
val3 1
val4 1
recordstart
val1 1
val2 3
val3 6
Your adjusted awk script with some adjustments:
sunt2000/user777$ cat ./test.sh
awk '
$1 == "recordstart" && FirstLine=="No" { FirstChar="Yes" ; print "" }
$1 == "recordstart" && FirstLine!="No" { FirstChar="Yes" ; FirstLine="No" }
$1 != "recordstart" && FirstChar=="No" { FirstChar="No" ; printf "," $2 }
$1 != "recordstart" && FirstChar!="No" { FirstChar="No" ; printf $2 }
END { print "" }' test.in
The output would look like this:
sunt2000/user777$ ./test.sh
1,2,4
5,6,1,1
1,3,6
If you are running on a real POSIX compliant platform, you will have multiple versions of awk. The "nawk" tool has more functionality in regard to some built-in variables than "awk" and "/usr/xpg4/bin/awk" has the ability to hold open more simultaneous file handles.
I took the sample data set provided in the thread, repeated it until the input file was 364 lines long, and processed the file 260 times on the "*awk" command line. The aggregate size of all data sets was 1.7MB.
On a slow box, I get the following performance results:
awk: real: 0m4.21s, 0m4.21s, 0m4.24s
awk: user: 0m4.17s, 0m4.18s, 0m4.21s
awk: sys: 0m0.02s, 0m0.02s, 0m0.02s
/usr/xpg4/bin/awk: real: 0m3.37s, 0m3.45s, 0m3.40s
/usr/xpg4/bin/awk: user: 0m3.33s, 0m3.42s, 0m3.38s
/usr/xpg4/bin/awk: sys: 0m0.02s, 0m0.02s, 0m0.02s
nawk real: 0m1.75s, 0m1.66s, 0m1.72s
nawk user: 0m1.71s, 0m1.63s, 0m1.69s
nawk sys: 0m0.02s, 0m0.02s, 0m0.02s
You can get a 2x-3x boost in speed, by merely adjusting which "*awk" you use.
Removing the 'H and 'D is a simple step in awk. Let's adjust your sample datafile, and repeat it the same number of times in the previous timing example:
sunt2000/user777$ cat ./test.in3
recordstart
val1 1'H
val2 2'D
val3 4
recordstart
val1 5
val2 6
val3 1'H
val4 1'H
recordstart
val1 1
val2 3
val3 6
...
sunt2000/user777$ cat ./test3.awk
/'H/ { gsub("'H","") }
/'D/ { gsub("'D","") }
$1 == "recordstart" && FirstLine=="No" { FirstChar="Yes" ; print "" }
$1 == "recordstart" && FirstLine!="No" { FirstChar="Yes" ; FirstLine="No" }
$1 != "recordstart" && FirstChar=="No" { FirstChar="No" ; printf "," $2 }
$1 != "recordstart" && FirstChar!="No" { FirstChar="No" ; printf $2 }
END { print "" }
Now, we will adjust the nawk script to remove them, and time the results against over 200 files where each file has thousands of lines:
sunt2000/user777$ time nawk -f test3.awk test.in3 test.in3 test.in3 ...
nawk real: 0m2.39s, 0m2.40s, 0m2.26s
nawk user: 0m2.35s, 0m2.36s, 0m2.24s
nawk sys: 0m0.03s, 0m0.02s, 0m0.02s
The results were just slightly slower adding the stripping.
You can shave off 0.10s more regularly, by avoiding the compares and just force the "gusb" for the 'H and 'D just before the "printf", all time.
sunt2000/user777$ cat test.awk4
$1 == "recordstart" && FirstLine=="No" { FirstChar="Yes" ; print "" }
$1 == "recordstart" && FirstLine!="No" { FirstChar="Yes" ; FirstLine="No" }
$1 != "recordstart" && FirstChar=="No" { FirstChar="No" ; gsub("'H","") ; gsub("'D","") ; printf "," $2 }
$1 != "recordstart" && FirstChar!="No" { FirstChar="No" ; gsub("'H","") ; gsub("'D","") ; printf $2 }
END { print "" }
sunt2000/user777$ time nawk -f test4.awk test.in3 test.in3 test.in3 ...
nawk real: 0m2.21s, 0m2.26s, 0m2.26s
nawk user: 0m2.18s, 0m2.24s, 0m2.24s
nawk sys: 0m0.02s, 0m0.03s, 0m0.02s
In total, "nawk" is faster than "/usr/xpg4/bin/awk", which is faster than "awk".
Global substitutions can be easily managed in awk.