Sunday, March 29, 2009

Four Ways to Pass Shell Variables in AWK

As we all know, not everyone is equal. This applies to AWK too. AWK in Solaris is a very old implementation compared the GNU AWK.

Here I am trying to show you 4 different ways to pass shell variable value to AWK

  1. This trick works on all flavours of AWK because it is taking advantage of shell substitution. Remember not to leave any space when you include a single quote, dollar variable, and a single quote in the AWK command
    $ one=111
    
    $ two=222
    
    $ awk 'BEGIN{a='$one';b='$two'}END{print a,b}' /dev/null
    111 222
    
  2. This works for all flavours of AWK too. AWK allows you to set their variable from the shell
    $ one=111
    
    $ two=222
    
    $ awk 'END{print a,b}' a=$one b=$two /dev/null
    111 222
    
  3. This will not work for Solaris awk. You have to use nawk. The -v flag allows you to assign AWK variable.
    $ one=111
    
    $ two=222
    
    $ nawk -v a=$one -v b=$two 'END{print a,b}' /dev/null
    111 222
    
  4. If your awk allows you to access the shell environment variables, you can use this trick. FYI, this will not work for Solaris awk.
    $ one=111
    
    $ two=222
    
    $ a=$one b=$two awk 'END{print ENVIRON["a"],ENVIRON["b"]}' /dev/null
    111 222
    

Labels: ,

Sed is Slow for Very Long Stream in Solaris, Part 2

A month ago, I reported that Solaris sed was very slow in handling very long stream.

I just downloaded the GNU sed (version: 4.1.5) from Sunfreeware and carried out the same experiment. Guess what, GNU sed runtime is 16s (131 times better than the Solaris sed, 3 times worse than the default perl 5.8.4).

Although I am a fan of Solaris, I really do not understand why the Solaris sunfreeware /usr/sfw (or /opt/sfw for Solaris 8) does not come with some of these utilities like sed. Also, most of the binaries in /usr/sfw are pretty old version.

Labels: ,

Tuesday, March 24, 2009

AWK Can Do Lookup, with ease

Some time ago, I blogged about AWK can do lookup. In fact, you can handle that with ease if your AWK supports FNR. FNR is the input record number in the current input file. If the first filename to AWK contains the lookup mapping, you can get AWK to store the lookup if FNR==NR. FNR==NR is always true for the first file processed by AWK. For subsequent files, FNR will be reset to 1 and therefore FNR==NR condition will no longer be true.

Below simple example demonstrates the power of FNR

file1.txt contains the lookup mapping and lookup will be applied to file2.txt and file3.txt

$ cat file1.txt
1 First
2 Second
3 Third
4 Fourth
5 Fifth

$ cat file2.txt
swimming 1
table-tennis 3
cycling 2
running 1
tennis 3

$ cat file3.txt
perl 4
python 3
tcl 2
shell-script 2

$ awk 'FNR==NR{map[$1]=$2;next}{print $1,map[$2]}' file1.txt file2.txt file3.txt
swimming First
table-tennis Third
cycling Second
running First
tennis Third
perl Fourth
python Third
tcl Second
shell-script Second

FYI, Solaris /usr/bin/awk does not support FNR and you have to use nawk

Labels: