From the Canyon Edge -- :-Dustin

Thursday, August 26, 2010

Buy 1, get 8 Free! Or, a Useful Awk Hack...

But first, a couple of updates...
  1. If you appreciated my errno post, you might be happy to know that /usr/bin/errno is now provided by the ubuntu-dev-tools package in Maverick. This probably won't be the permanent home for the utility (currently in discussions with Joey Hess about putting it in moreutils, and the kernel team about putting it in linux-tools). But while we debate among ourselves about the permanent location of the bike shed, you -- our Ubuntu users -- are welcome to go about using the tool.
  2. And if you liked my bash alert post, you might also be happy to know that the alert alias is also in Maverick's skeleton .bashrc. This only affects new Maverick installs, and you'll have to install the libnotify-bin package, but still, it's a useful tool, and a good start. Several people have suggested UDS-Natty sessions on how to make the tool more universally useful, and it would be cool to see those move forward in the next cycle.
Okay, now for another fun set of tools!

All too often, I found myself typing something like this:
... | awk -F":" '{print $3}'
That's a lot of wasted characters, and it's easy to flub them up.

And so I generalized it, with this 2-line shell script in /home/kirkland/bin/1:
[ -n "$1" ] && ifs="-F\"$1"\" || ifs=
eval awk $ifs "'{print \$$(basename $0)}'" /dev/stdin

And then I made symlinks to this one script, for numbers 2-9:
cd $HOME/bin
for i in $(seq 2 9); do
ln -s 1 $i

And now I can:
errno "" | 1
euca-describe-instances | 2
cat /etc/passwd | 7 :

I started out with just simple aliases for 1..9, but I found myself often needing to change the input field separator (IFS). In case you'd prefer the simple aliases, you can use these:
for i in $(seq 1 9); do
alias $i="awk '{print \$$i}'"

What do you think?
  • Would you like to see these as /usr/bin/1 ... /usr/bin/9 in Ubuntu Natty?
  • Do you have a more efficient implementation?


p.s. My wife, Kim, took both of these pictures recently, on the side of the road in Michigan and New York, respectively. Pretty birds, hard to photograph! :-)


  1. This looks evil.. glad you aptly labeled it as a "hack" :)

  2. In general, its a good idea to avoid eval. Below is a solution without eval. Before you get on my case and tell me that '${2:+}' didn't work in some ancient versions of /bin/sh, i don't really care. If you do, change it to /bin/bash.

    Second thing i like is it doesn't rely on being named something specific. 'fno' or 'field number' requires input of a field. you can then easily set up aliases to pass it that field, as shown below.

    $ cat ~/bin/fno
    # arg1=field number # arg2 = optional field separator
    [ -n "${1}" -a "${1#[0-9]}" != "${1}" ] ||
    { echo "bad input to ${0##*/}: $*" 1>&2; exit 1; }
    exec awk ${2:+"-F${2}"} '{print $'"$1"'}'

    $ for x in $(seq 1 9); do alias $x="fno $x"; done
    $ echo "one two three four five" | fno 5
    $ echo "one two three four five" | 4
    $ echo "one:two:three:four:five" | 2

    $ echo "one:two:three:four:five" | 2 :

  3. You really shouldn't use such generic names; it's probably best to namespace them instead: $namespace-1..9. Otherwise, that's a good idea.

  4. and, accusing people of attempting to help you get your tool placed into the most appropriate place (it's certainly /not/ an Ubuntu development tool) of bikeshedding is a great way to demotivate them. Nice one.

  5. "When systems programming, do you ever find yourself with an unfamiliar error code, and then you're off Googling what the heck it actually means?"

    Never. I read the manuals of the functions I use and account for the errors that might occur. It shouldn't happen that you find yourself with the actual _number_ of the error code. You should rather print a/the message associated with the error as it is handled in your program. Like... right? I mean, am I alone in this methodology?


Please do not use blog comments for support requests! Blog comments do not scale well to this effect.

Instead, please use Launchpad for Bugs and StackExchange for Questions.