Hacker News new | ask | show | jobs
by troydj 3283 days ago
I learned Awk in 1988 before Perl was around (on our systems, anyway). It was super useful at the time. But if you know Perl and Perl is available on your system, there's certainly not a compelling need for writing standalone, multi-line Awk programs. But Awk is really, really useful for one-liners. As Larry Wall has said: "I still say awk '{print $1}' a lot."

Brian Kernighan himself, in this 2015 talk [1] on language design, states that Awk was primarily intended for one-liner usage (he mentions this at 20:43).

[1] https://youtu.be/Sg4U4r_AgJU?t=19m45s

4 comments

I don't have it in writing or video, but in 2008 at ACM Reflections/Projections at University of Illinois I was involved in a long conversation with Larry Wall and Al Aho. It was largely about the history and lineage of programming languages.

Al said that if Perl had existed first there wouldn't have been an awk. I pointed out that parts of Perl are inspired by awk and might have otherwise been inspired by SNOBOL or ICON, at which point everyone present seemed to agree means we're thankful for awk. I take it as high praise when Al Aho defers to your tool.

I was just reminiscing with Larry about that discussion last week at The Perl Conference in Arlington. He said he had fond memories of that conversation and that he and Al went for lunch the next day after that conversation, too. I'd have loved to be there for that.

Once I learned Perl I never used awk or sed again. Even for one liners with the -n -p -a options you can easily write one liners in Perl that are concise as those in Awk.
How do you write

    awk '{print $3 ":" $1 " " $2}'
in Perl?

  perl -aE 'say "$F[2]:$F[0] $F[1]"'
That's indeed concise, but it doesn't work. I think you need -naE
-a implies -n since v5.19.3.
One way would be:

   perl -nae'printf("%s:%s %s\n",$F[2],$F[0],$F[1])'
I would not call that "as concise as awk"
Lisp:

  $ txr -e '(awk ((prn `@[f 2]:@[f 0] @[f 1]`)))'
  1 2 3
  3:1 2
How about input from a string stream? At the REPL:

  1> (with-in-string-stream (*stdin* "1 2 3")
       (awk ((prn `@[f 2]:@[f 0] @[f 1]`))))
  3:1 2
  nil
It pays not to have awk be some some canned global behavior enabled by a command line option.
Another way, without using a quasiliteral: just set the output field separator (ofs) to empty string, and prn:

  txr -e '(awk (:set ofs "") ((prn [f 2] ":" [f 0] " " [f 1])))'
This is like:

  awk -v OFS= '{print $3, ":", $1, " ", $2}'
I've written reasonably complicated stuff in awk (like a page or two of code). Probably could have solved those problems more elegantly with another tool, but I never learned perl, and I find awk simple enough that the man page is all I need to refresh my memory. For text manipulation that's a one-off or likely to not need further maintenance, I think it's great.
Back at Netcraft for the data crunching pipelines for the surveys we tended to start off with sed+awk for expressivity/concision of operations and then rewrite in perl later for performance.