Skip to content

/flags/awk/awk-v-assign-variable

awk -v var=value: pass a shell variable into an awk program

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · GNU Awk 5.4.1updated
tool
awk
command
awk
flag
-v var=value
default
no variables assigned; an unset awk variable is the empty string (0 in arithmetic)

awk -v limit="$LIMIT" '$3 > limit' data.txt copies the shell value into the awk variable limit before the program starts. That is the safe way to use shell variables in awk: the program stays in single quotes, so the shell never edits it, and the value cannot break the program's syntax. Inside the program the variable is written without $; $limit would mean "the field whose number is the value of limit".

Syntax

-v var=value (GNU long form --assign=var=value) can be repeated, one assignment per -v. The assignment happens before the BEGIN block, so the value is available everywhere. It is POSIX, so it works the same in gawk, mawk, BusyBox awk and the BSD/macOS awk.

bash
n=2
echo 'apple 3' | awk -v n="$n" -v unit=kg '{ print $1, $2 * n, unit }'
awk -v 'msg=hello world' 'BEGIN { print msg }'
echo x | awk -v v=early 'BEGIN { print "begin:" v } { print "main:" v }'
echo x | awk 'BEGIN { print "begin:[" v "]" } { print "main:" v }' v=late

Output

apple 6 kg
hello world
begin:early
main:early
begin:[]
main:late

The last two lines show the difference with an operand assignment (v=late after the program): it runs only when awk reaches it in the argument list, after BEGIN, so BEGIN sees an empty value.

Escape sequences in the value

The value is processed like an awk string literal: \t, \n and \\ are interpreted. That is handy for separators and wrong for paths:

bash
awk -v sep='\t' 'BEGIN { printf "a%sb\n", sep }' | od -c | head -1
awk -v p='C:\new' 'BEGIN { print p }'
p='C:\new' awk 'BEGIN { print ENVIRON["p"] }'

Output

0000000   a  \t   b  \n
C:
ew
C:\new

ENVIRON["name"] reads an exported environment variable without escape processing, so it is the right choice for arbitrary data such as file paths or user input. An unknown escape such as \q produces the escape sequence treated as plain warning.

Ways to get a value into awk

MethodWhen it is assignedEscapes processedNotes
-v var=valuebefore BEGINyesPOSIX; repeat -v for each variable
var=value operandwhen awk reaches it among the filesyesCan change a value between two input files
ENVIRON["var"]any timenoThe variable must be exported (or set on the command line)
"$var" spliced into the programby the shelln/aFragile: quotes or spaces in the value break or alter the program

Errors

The name must be a valid awk identifier and the argument must contain =:

bash
awk -v 2x=1 'BEGIN { }'

Output · exit 2

awk: fatal: `2x' is not a legal variable name

awk -v x without =value makes gawk complain that the argument to -v is not in var=value form, print its usage text and exit 1. Assigning a built-in such as -v FS=, is allowed and is equivalent to -F, (see awk -F).

Numbers

A value that looks like a number compares numerically (POSIX calls it a numeric string), so -v limit=10 with $3 > limit compares 9 > 10 as numbers, not as text. gawk does not treat 0x1A or 010 as hexadecimal or octal in input data unless --non-decimal-data is given; 010 is simply 10.

FAQ

Why does my shell variable not work inside the awk program?

The program is in single quotes, so the shell does not expand $name there, and inside awk $name means a field. Pass the value with -v name="$name" and use name (without $) in the program.

What is the difference between -v x=1 and x=1 after the program?

-v assigns before BEGIN runs. An assignment written among the file operands runs only when awk reaches that position, after BEGIN, so BEGIN sees an empty variable.

How do I pass a value that contains backslashes, such as a Windows path?

-v processes escape sequences, so C:\new becomes C: plus a newline. Export the value and read it with ENVIRON["name"], which awk takes literally.

Sources