Back in February, I wrote about printing out a separator in Bash. At the time, I thought it’s a bit pain in the butt, but when I encountered punchcard.awk and tried to save a few LOC, AWK is even more painful. There is no string repetition nor Brace Expansion.

1   Solutions

These are how you can do it:


BEGIN {
LENGTH = 40;
# AWK
sep = sprintf("%*s", LENGTH, "");
gsub(/ /, "-", sep);
print "start <", sep, "> end";
# GNU AWK
print gensub(/0/, "-", "g", sprintf("start < %0*d > end", LENGTH, 0));
# Really, seriously?
printf("start < ");
for (i=0; i<LENGTH; i++) {
printf("-");
}
printf(" > end\n");
}

start < ---------------------------------------- > end
start < ---------------------------------------- > end
start < ---------------------------------------- > end

If you use GNU AWK, then you can have a real one-liner, however, it’s still looks a bit weird for me.

The methods are different in two cases above, one uses %d, the other uses %s. They are very much the same, only %d with 0 padding can be very useful if the separator has some extra stuff with, same may not be same with space padding.

2   Speedtest

2.1   AWK


time awk -e 'BEGIN {
LENGTH = 58;
for (i=0; i<1000; i++) {
sep = sprintf("%*s", LENGTH, "");
gsub(/ /, "-", sep);
print sep;
}
}'
>/dev/null

real 0m0.022s
user 0m0.020s
sys 0m0.002s

2.2   GNU AWK


time awk -e 'BEGIN {
LENGTH = 58;
for (i=0; i<1000; i++) {
print gensub(/ /, "-", "g", sprintf("%*s", LENGTH, ""));
}
}'
>/dev/null

real 0m0.020s
user 0m0.018s
sys 0m0.001s

2.3   Really, seriously?


time awk -e 'BEGIN {
LENGTH = 58;
for (i=0; i<1000; i++) {
printf("start < ");
for (j=0; j<LENGTH; j++) {
printf("-");
}
printf(" > end\n");
}
}'
>/dev/null

real 0m0.024s
user 0m0.023s
sys 0m0.000s

2.4   Bash

I picked one of fastest methods from the post for Bash, there are more way of what you can do in Bash.


time for i in {1..1000}; do printf -v sep '%*s' 58 ; echo "${sep// /-}" >/dev/null ; done

real 0m0.080s
user 0m0.073s
sys 0m0.006s

Clearly, no doubt that AWK beats Bash. ~20ms over ~80ms.

3   Thought

AWK is an interesting language, sometimes I like it, sometimes I don’t. When you have written same task in different languages, you always feel something is missing in a language.

There is nothing wrong with Really, seriously? method and to be frankly, it is more readable and clearer than using gsub or gensub. Just you would feel it’s as if you were still doing some exercise in the text book, you know like “how to use loop.”

Will I use those, certainly will for sake’s of LOC and already have. There are not really too hard to understand and not overly ugly in my opinion. And most importantly, they are fastest methods, though looping method itself doesn’t look bad at all.