4 ms·
You can definitely use awk (I use it myself). But lets not pretend it’s readable for anyone after the original writer. It has a single purpose and that is to ge
by nafizh 5y ago
You can definitely use awk (I use it myself). But lets not pretend it’s readable for anyone after the original writer. It has a single purpose and that is to get the text munging task in front of you done as quickly as possible.
- dundarious 5y agoI disagree. The scripts in the article are very readable, and my personal experience has been that short awk scripts are as messy/unreadable as short scripts in any other language — or as clean/readable. I don’t even think this would be different for longer scripts.
- kazinator 5y agoAwk 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") }
- winrid 5y agoI'm surprised at how close to JS it appears. I wonder how much better off you'd be just writing it in Node.