Main index

Introducing UNIX and Linux


Awk

Overview
What is 'awk'?
Invoking 'awk'
Naming the fields
Formatted output
      Operators used by Awk
Patterns
Variables
      Accessing Values
      Special variables
Arguments to 'awk' scripts
Arrays
Field and record separators
Functions
      List of Awk functions
Summary
Exercises

Arguments to 'awk' scripts

Suppose we wished to write a shell script called price, which would take one argument, representing a vegetable name, and interrogate the file vegetables as before to display the total price paid for that vegetable. One solution would be to get Awk to evaluate the total cost for all vegetables, and then use Grep to filter out the single line of output from awk:

awk '{ printf "%s %.2f\n", $1, $2*$3 }' vegetables | grep $1

Note that in grep $1, the $1 refers to the first argument of the shell script.

This is a perfectly acceptable solution. Another would be to use a pattern for awk so that only that single line would be processed by awk. But here is a problem - we cannot use the following:

awk '/$1/ { printf "%s %.2f\n", $1, $2*$3 }' vegetables

The pattern /$1/ is an ERE pattern. The character $ in an ERE matches the end of a string, and since each record Awk processes is a line, $ matches the end of an input line. The ERE $1, and thus the awk pattern /$1/, will match all lines containing the digit 1 as the character after the end of that line. This an impossible pattern, so it will not be matched by any line. Try it - you should expect not to get any output. The point to remember is that the $1 has nothing to do with the $1 that would represent the first argument to a shell script.

There is, fortunately, a way around this problem. When invoking awk you can preset Awk variables by specifying their initial value on the command line. So, we could assign an Awk variable called veg (say), which would start off with the value that was the first argument to the script:

awk '{ if (veg == $1)
         printf "%s %.2f\n", $1, $2*$3 }' veg=$1 vegetables

By placing veg=$1 immediately after the Awk script, it will set the value of veg to $1 - the first argument to the shell script - as soon as awk starts up. Another method would be to use veg as part of a pattern:

awk ' veg == $1
       { printf "%s %.2f\n", $1, $2*$3 }' veg=$1 vegetables

Worked example

Write a shell script to take a single argument, representing a cost in pence, and print out the names of all vegetables listed in file vegetables that cost more than that number of pence per kilo.
Solution: Use awk, but pass a variable cost to it that is set to the first argument of the shell script.

# First, check the shell script has one argument
if   [ $# -ne 1 ]
then echo "One argument needed"
     exit 1
fi

# Now fire awk ...
awk '{ if ($2 * 100 >= cost)
            printf "%s\n", $1 }' cost=$1 vegetables

# Exit cleanly
exit 0

Copyright © 2002 Mike Joy, Stephen Jarvis and Michael Luck