awk Cheatsheet

Operators and Expressions

Use this awk reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Operator table, highest precedence first

OperatorsNotes
$field reference, binds tighter than everything
++ --prefix and postfix
^exponentiation, right associative (2^3^2 is 512)
! - +unary
* / %% is fmod, so it works on non-integers
+ -addition
(nothing)string concatenation, a b glues a and b
< <= > >= != ==comparison, numeric or string (see below)
~ !~regex match
inarray membership
&&logical and, short-circuits
||logical or, short-circuits
?:ternary, right associative
= += -= *= /= %= ^=assignment, right associative
awk 'BEGIN{ print 2^3^2 }'          # 512, not 64
awk 'BEGIN{ print 7 % 3, -7 % 3 }'  # 1 -1
awk 'BEGIN{ print 10 % 3.5 }'       # 3

Concatenation has no operator, and that hurts

Two expressions side by side concatenate. Since + binds tighter than concatenation, and concatenation binds tighter than comparison, spacing is cosmetic but grouping is not.

awk 'BEGIN{ print "a" 1+1 }'        # a2
awk 'BEGIN{ print 1 " " 2 }'        # 1 2
awk 'BEGIN{ print -1 " " -1 }'      # -1-1   <-- (-1) then (" " - 1)
awk 'BEGIN{ print 1 " " 2 - 1 }'    # 1 1    <-- 1 then (" " 2) - 1
awk 'BEGIN{ print (1 == 1 "x") }'   # 0      <-- 1 == "1x", a string compare
awk 'BEGIN{ print (-1) " " (-1) }'  # -1 -1  <-- what you meant

Wrap anything ambiguous in parentheses. The -1 " " -1 case is the one people lose an hour to, the " " is eaten as the left operand of a subtraction.

String versus numeric comparison

The rule: a comparison is numeric only when both sides are numbers or look like numbers and came from the input. Otherwise it is a string comparison.

Both sidesComparison
number and numbernumeric
field / getline var / -v var / ARGV / ENVIRON that looks numericnumeric ("strnum")
string constant, or result of concatenationstring
awk 'BEGIN{ if ("10" < "9") print "string" }'        # prints, "1" < "9"
echo "10 9" | awk '{ if ($1 > $2) print "numeric" }' # prints, fields are strnum
awk -v x=10 'BEGIN{ print (x > 9) }'                 # 1, -v values are strnum
awk 'BEGIN{ x="10"; print (x == 10) }'               # 1, the constant coerces

Force the comparison you want:

$1 + 0 == $2 + 0        # definitely numeric
$1 "" == $2 ""          # definitely string

Leading and trailing blanks and a + sign still count as numeric, so the field 10 compares as 10. A field like 10abc is not numeric, and 10abc + 0 is 10.

Truthiness and uninitialized values

An uninitialized variable is both 0 and "" at once, and it is false.

awk 'BEGIN{ print x+0, "["x"]", length(x), (x?"t":"f") }'   # 0 [] 0 f
ValueTruthy?
0, 0.0no
""no
uninitializedno
"0" (string constant)yes
a field holding 0no, it is a strnum
any other non-empty stringyes

That split is why if ($3) and if ($3 != "") behave differently on a column of zeroes.

Increment, assignment, and the !seen[$0]++ idiom

Postfix ++ yields the old value, then increments. On an array element it also creates the element.

# dedupe: first time seen[$0] is 0 (false), !0 is true, then it becomes 1
awk '!seen[$0]++' file

# number only the duplicates
awk '{ n = ++count[$1]; if (n > 1) print n, $0 }' file

# compound assignment on a field rebuilds $0
printf '1 2\n' | awk '{ $1 *= 10; print }'   # 10 2

Redirect versus greater-than

Inside print and printf, > means redirect to a file. There is no way for awk to tell your comparison apart, so parenthesize it.

awk 'BEGIN{ print 1 > 2 }'      # creates a file named "2" containing "1"
awk 'BEGIN{ print (1 > 2) }'    # prints 0
awk 'BEGIN{ x = 1 > 2; print x }'  # fine, assignment context is unambiguous

The same trap applies to >> and |. >=, <, and == are safe, only > and >> are overloaded.