How do I use shell variables in an awk script?
#Getting shell variables into
awk
may be done in several ways. Some are better than others. This should cover most of them. If you have a comment, please leave below. v1.5
##Using -v
(The best way, most portable)Use the -v
option: (P.S. use a space after -v
or it will be less portable. E.g., awk -v var=
not awk -vvar=
)
variable="line one\nline two"awk -v var="$variable" 'BEGIN {print var}'line oneline two
This should be compatible with most awk
, and the variable is available in the BEGIN
block as well:
If you have multiple variables:
awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'
Warning. As Ed Morton writes, escape sequences will be interpreted so \t
becomes a real tab
and not \t
if that is what you search for. Can be solved by using ENVIRON[]
or access it via ARGV[]
PS If you like three vertical bar as separator |||
, it can't be escaped, so use -F"[|][|][|]"
Example on getting data from a program/function inn to
awk
(here date is used)
awk -v time="$(date +"%F %H:%M" -d '-1 minute')" 'BEGIN {print time}'
Example of testing the contents of a shell variable as a regexp:
awk -v var="$variable" '$0 ~ var{print "found it"}'
##Variable after code blockHere we get the variable after the awk
code. This will work fine as long as you do not need the variable in the BEGIN
block:
variable="line one\nline two"echo "input data" | awk '{print var}' var="${variable}"orawk '{print var}' var="${variable}" file
- Adding multiple variables:
awk '{print a,b,$0}' a="$var1" b="$var2" file
- In this way we can also set different Field Separator
FS
for each file.
awk 'some code' FS=',' file1.txt FS=';' file2.ext
- Variable after the code block will not work for the
BEGIN
block:
echo "input data" | awk 'BEGIN {print var}' var="${variable}"
##Here-stringVariable can also be added to awk
using a here-string from shells that support them (including Bash):
awk '{print $0}' <<< "$variable"test
This is the same as:
printf '%s' "$variable" | awk '{print $0}'
P.S. this treats the variable as a file input.
##ENVIRON
inputAs TrueY writes, you can use the ENVIRON
to print Environment Variables.Setting a variable before running AWK, you can print it out like this:
X=MyVarawk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'MyVar /bin/bash
##ARGV
inputAs Steven Penny writes, you can use ARGV
to get the data into awk:
v="my data"awk 'BEGIN {print ARGV[1]}' "$v"my data
To get the data into the code itself, not just the BEGIN:
v="my data"echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"my data test
##Variable within the code: USE WITH CAUTIONYou can use a variable within the awk
code, but it's messy and hard to read, and as Charles Duffy
points out, this version may also be a victim of code injection. If someone adds bad stuff to the variable, it will be executed as part of the awk
code.
This works by extracting the variable within the code, so it becomes a part of it.
If you want to make an awk
that changes dynamically with use of variables, you can do it this way, but DO NOT use it for normal variables.
variable="line one\nline two"awk 'BEGIN {print "'"$variable"'"}'line oneline two
Here is an example of code injection:
variable='line one\nline two" ; for (i=1;i<=1000;++i) print i"'awk 'BEGIN {print "'"$variable"'"}'line oneline two123..1000
You can add lots of commands to awk
this way. Even make it crash with non valid commands.
One valid use of this approach, though, is when you want to pass a symbol to awk to be applied to some input, e.g. a simple calculator:
$ calc() { awk -v x="$1" -v z="$3" 'BEGIN{ print x '"$2"' z }'; }$ calc 2.7 '+' 3.46.1$ calc 2.7 '*' 3.49.18
There is no way to do that using an awk variable populated with the value of a shell variable, you NEED the shell variable to expand to become part of the text of the awk script before awk interprets it.
##Extra info:###Use of double quoteIt's always good to double quote variable "$variable"
If not, multiple lines will be added as a long single line.
Example:
var="Line oneThis is line two"echo $varLine one This is line twoecho "$var"Line oneThis is line two
Other errors you can get without double quote:
variable="line one\nline two"awk -v var=$variable 'BEGIN {print var}'awk: cmd. line:1: one\nlineawk: cmd. line:1: ^ backslash not last character on lineawk: cmd. line:1: one\nlineawk: cmd. line:1: ^ syntax error
And with single quote, it does not expand the value of the variable:
awk -v var='$variable' 'BEGIN {print var}'$variable
###More info about AWK and variablesRead this faq.
Use either of these depending how you want backslashes in the shell variables handled (avar
is an awk variable, svar
is a shell variable):
awk -v avar="$svar" '... avar ...' fileawk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file
See http://cfajohnson.com/shell/cus-faq-2.html#Q24 for details and other options. The first method above is almost always your best option and has the most obvious semantics.