
For a list of BASHing data 2 blog posts see the index page.
Five ways to pass a shell variable to AWK
My shell scripts often contain a (GNU) AWK command, and that command often references a shell variable defined earlier in the script. My usual way of passing the shell variable to AWK is to define an AWK variable with it, as in the following simple example. I have a list of numbers ("nos") and I want to see if any of them are less than some other number (in this case, 17), and I assign that number to the shell variable "level". I use AWK to do the test after attaching "level" to the AWK variable "try" with AWK's -v (for "variable") option, like this:
printf "10\n20\n30\n" > nos
level="17"
awk -v try="$level" '$0 < try' nos

Another easy method is to put the AWK variable assignment after the command and before the filename argument:
awk '$0 < try' try="$level" nos

The above two methods generally work well unless there are escaped strings in the shell variable; the shell will interpret these before AWK sees them.
Now for three fairly crafty methods. The first is to temporarily escape the AWK command with single quotes and insert the quoted variable, which BASH knows how to interpret:
awk '$0 < '"$level"'' nos

The second crafty method relies on AWK's ARGV array, which AWK uses to store the arguments following the AWK command. "ARGV[1]" is the first argument, "ARGV[2]" is the second argument, and so on,
awk 'BEGIN {hippo=ARGV[1];ARGV[1]=""} $0 < hippo' "$level" nos

The craftiness here is in the BEGIN statement. There I define "hippo" as the first argument (ARGV[1]) after the command, namely "$level". This will allow AWK to test the lines in "nos" to see which one is less than 17, but I've also said that "$level" is blank (ARGV[1]=""), so when AWK finishes with BEGIN and gets to the arguments, it doesn't see the first one and only works with "nos". Weird, yes?
The fifth method is seriously crafty. AWK has an "ENVIRON" array in which it stores the environment variables used in your system. These are items like "USER", "PWD" and "LANG" that you can see listed by entering env or export in a terminal. The ENVIRON array is indexed with the name of the variable, and the value string in the array is the variable's definition. If I define "level" as "17" and export it, it becomes an environment variable:

I can now reference the shell variable indirectly in an AWK command:
level="17"
export level
awk '$0 < ENVIRON["level"]' nos

When I end my terminal session, "level" disappears from the list of environment variables. A concern here might be the risk of replacing an existing environment variable with a temporary one. It's therefore best to use temporary names that aren't already on the system (do a check with env or export) and are unlikely to ever be there, like "RHINOCEROS" or "Galadriel".
I've seen the ENVIRON method described as the safest one, but I'm a boring and un-crafty AWK user and the -v [AWK variable]="$[shell variable]" method is the one I prefer to use.
Next post:
2025-07-04 Data entry with unknown data categories
Last update: 2025-06-27
The blog posts on this website are licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License