Awk code, especially throwaway one-liners, can be quite readable. And if not so absolutely, then better than the alternatives.

Awk is not actually very good for text munging, by the way; it's for munging semi-numerical text in a record and field format.

It has hidden pitfalls, like objects being treated as numeric strings, depending on which source they came from.

If a and b came from a positional field then a == b is true if a is "5.00" and b is "0.5E1". But "5.00" == "0.5E1" is false. If you want to ensure a string comparison, and it's not clear in the code what the provenance is of the arguments, you have to do something like a "" == b: catenate an empty string to force string mode. Likewise in some situations you have do a + 0 == b to force numeric.

The text processing in Awk fairly poor, and the core of it is just a handful of library functions that have nicer implementations in other languages.

Here is GNU Awk code I wrote in 2014 for parsing a regex: not a problem of parsing records with semi-numerical fields. It's a ecursive descent job just to validate the syntax, not to translate it to anything:

#!/usr/bin/gawk -f

function empty(s)
{
return s == ""
}

function eat_char(s)
{
return substr(s, 2)
}

function eat_chars(s, n)
{
return substr(s, n + 1)
}

function matches(s, pfx)
{
return substr(s, 1, length(pfx)) == pfx
}

function match_and_eat(s, pfx)
{
if (matches(s, pfx))
return eat_chars(s, length(pfx))
return s
}

function eat_rchar(c)
{
if (c ~ /^\\./)
return eat_chars(c, 2)

if (c == "$")
return c

if (c !~ /^[\[\*\+\?{}\(\)|]/)
return eat_char(c)

return c
}

function eat_bchar(c)
{
if (c ~ /^\\]|\\-|\\\\/)
return eat_chars(c, 2)

if (c !~ /^[\-\[]/)
return eat_char(c)

return c
}

function eat_class(c)
{
c = match_and_eat(c, "[:alnum:]")
c = match_and_eat(c, "[:alpha:]")
c = match_and_eat(c, "[:blank:]")
c = match_and_eat(c, "[:cntrl:]")
c = match_and_eat(c, "[:digit:]")
c = match_and_eat(c, "[:graph:]")
c = match_and_eat(c, "[:lower:]")
c = match_and_eat(c, "[:print:]")
c = match_and_eat(c, "[:punct:]")
c = match_and_eat(c, "[:space:]")
c = match_and_eat(c, "[:upper:]")
return match_and_eat(c, "[:xdigit:]")
}

function eat_bracket_exp(e,
#local
f, o)
{
o = e
e = eat_char(e)

for (;;) {
if (matches(e, "]")) {
return eat_char(e)
}

if (matches(e, "[")) {
f = eat_class(e)
if (f == e)
return o
e = f
continue;
}

f = eat_bchar(e)

if (f == e)
return o
e = f

if (matches(e, "-")) {
e = eat_char(e)
f = eat_bchar(e)
if (f == e)
return o
e = f
}
}
}

function eat_rep_notation(n)
{
n = eat_char(n)

if (n !~ /^[0-9]/)
return n

while (n ~ /^[0-9]/)
n = eat_char(n)

if (matches(n, "}"))
return eat_char(n)

if (!matches(n, ","))
return n

n = eat_char(n)

if (matches(n, "}"))
return eat_char(n)

if (n !~ /^[0-9]/)
return n

while (n ~ /^[0-9]/)
n = eat_char(n)

return match_and_eat(n, "}")
}

function eat_factor(f)
{
if (matches(f, "("))
return match_and_eat(eat_regex(eat_char(f)), ")")

if (matches(f, "["))
return eat_bracket_exp(f)

return eat_rchar(f)
}

function eat_term(t,
#local
s)
{
s = eat_factor(t)

if (empty(s) || s == t)
return s

t = s

if (t ~ /^[?+*]/)
return eat_char(t)

if (matches(t, "{"))
return eat_rep_notation(t)

return t
}

function eat_regex(r,
#locals
s)
{
if (empty(r))
return r

s = eat_term(r)

if (empty(s) || s == r)
return s

r = s;

if (matches(r, "|"))
r = eat_char(r)

return eat_regex(r)
}

function is_regex(r)
{
if (matches(r, "^"))
r = eat_char(r)

if (empty(r))
return 1

r = eat_regex(r)

if (r == "$")
r = ""

return empty(r);
}

#{
# printf("eat_rep_notation(%s) = %s\n", $0, eat_rep_notation($0));
#}

{
# for (i = 0; i < 10000; i++)
# is_regex($0)
printf("is_regex(%s)\n", is_regex($0) ? "yes" : "no")
}