Difference between revision 3 and current revision

Summary: Rollback to 2011-07-04 22:12 UTC

No diff available.

Answer 1:

On Unix, use "alternate quoting", e.g.

        awk -F: '$1 ~ /'"$USER"'/ {print $5}' /etc/passwd

Any standard Unix shell will send the underlined part as one long argument (with embedded spaces) to awk, for instance:

        $1 ~ /bwk/ {print $5}

Note that there may not be any spaces between the quoted parts. Otherwise, you wouldn't end up a single, long script argument, because Unix shells break arguments on spaces (unless they are `escaped' with `\', or in '' or "", as the above example shows).

This approach should be avoided in general, unless it is the only one supported by your version of awk (which, in that case, should be upgraded anyway, and not just for this reason). The problem is that it cannot be trusted to work in general, and the outcomes are highly dependent on the actual content of the shell variables you are using. Some examples follow (taken from discussions on comp.lang.awk):

$ var="#"
$ awk 'BEGIN{ print '"$var"' }'
awk: cmd. line:1: BEGIN{ print # }
awk: cmd. line:1:              ^ syntax error

The above can be "corrected" by using double quotes in the awk program:

$ var="#"
$ awk 'BEGIN{ print "'"$var"'" }'

However, there are cases where even that is not enough:

$ var="hello
$ awk 'BEGIN{ print "'"$var"'" }'
awk: BEGIN{ print "hello
awk:              ^ unterminated string

That however works using -v:

$ var="hello
$ awk -v var="$var" 'BEGIN{ print var }'

See next answer for a description of -v:

Answer 2:

RTFM to see if and how your awk supports variable definitions on the command line, e.g.,

  awk -F: -v name="$USER" '$1 ~ name {print $5}' /etc/passwd

Answer 3

RTFM if your awk can access enviroment vars. Then perhaps

  awk -F: '$1 ~ ENVIRON["USER"] {print $5}' /etc/passwd

Always remember for your /bin/sh scripts that it's easy to put things into the environment for a single command run:

        name=felix age=56 awk '... ENVIRON["name"] .....'

this also works with ksh and some other shells.

The first approach is extremely portable, but doesn't work with awk "-f" script files. In that case, it's better to use a shell script and stretch a long awk command argument in '...' across multiple lines if need be.

Also note: /bin/csh requires a \ before an embedded newline, /bin/sh not.

See [1] for a very complete discussion of passing shell variables values to awk programs.