Beginner

Operators in AWK

Master arithmetic, comparison, logical, regex, and assignment operators in AWK with practical pattern-action examples

Operators are the building blocks of every AWK expression — they drive the calculations inside action blocks and the conditions inside patterns. Because AWK borrows much of its operator syntax from C, anyone with experience in C, Java, or JavaScript will recognize most of it immediately, but AWK adds two operator categories that make it special: regular expression match operators and an unusual “no operator” string concatenation.

AWK is a dynamically and weakly typed language, which means values fluidly switch between strings and numbers depending on context. The operator you choose tells AWK which interpretation to apply: + forces a numeric context, while string concatenation forces a string context. Understanding this duality is the key to writing correct AWK.

This tutorial walks through each operator family, how AWK’s pattern-action paradigm uses operators inside both patterns and actions, and the operator-driven idioms that make AWK programs concise.

Arithmetic Operators

AWK supports the standard arithmetic operators, plus exponentiation. All numeric values are double-precision floating-point internally.

OperatorMeaningExample
+Additiona + b
-Subtractiona - b
*Multiplicationa * b
/Division (float)a / b
%Moduloa % b
^Exponentiationa ^ b
**Exponentiation alta ** b
- (unary)Negation-a
+ (unary)Force numeric+a

Create a file named arithmetic.awk:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
BEGIN {
    a = 17
    b = 5

    print "a =", a, " b =", b
    print "a + b =", a + b
    print "a - b =", a - b
    print "a * b =", a * b
    print "a / b =", a / b
    print "a % b =", a % b
    print "a ^ b =", a ^ b
    print "-a    =", -a

    # Division is always floating-point in AWK
    print "10 / 3 =", 10 / 3

    # Use int() to truncate toward zero
    print "int(10/3) =", int(10 / 3)
}

Assignment and Increment Operators

AWK supports compound assignment operators and the C-style increment/decrement operators in both prefix and postfix forms.

OperatorMeaning
=Plain assignment
+=Add and assign
-=Subtract and assign
*=Multiply and assign
/=Divide and assign
%=Modulo and assign
^=Exponentiate and assign
++Increment (pre/post)
--Decrement (pre/post)

Create a file named assignment.awk:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
BEGIN {
    x = 10
    print "start    x =", x

    x += 5
    print "x += 5   x =", x

    x -= 3
    print "x -= 3   x =", x

    x *= 2
    print "x *= 2   x =", x

    x /= 4
    print "x /= 4   x =", x

    # Postfix returns old value, then increments
    y = 1
    print "post  y++ ->", y++, "after:", y

    # Prefix increments first, then returns
    z = 1
    print "pre  ++z ->", ++z, "after:", z

    # Uninitialized variables start at 0 (numeric) or "" (string)
    print "counter starts at:", counter
    counter++
    print "after counter++ :", counter
}

Comparison Operators and the String/Number Duality

Comparison operators return 1 for true and 0 for false. The interesting twist: AWK chooses between numeric and string comparison based on the operands. If both look like numbers, AWK compares numerically; otherwise it compares as strings (lexicographically).

OperatorMeaning
==Equal
!=Not equal
<Less than
<=Less than or equal
>Greater than
>=Greater or equal

Create a file named comparison.awk:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
BEGIN {
    # Numeric comparison
    print "10 > 9       :", (10 > 9)
    print "10 == 10.0   :", (10 == 10.0)

    # String comparison (lexicographic)
    print "\"10\" > \"9\"   :", ("10" > "9")     # 0 (false): "1" < "9"
    print "\"abc\" < \"abd\" :", ("abc" < "abd")  # 1

    # Force numeric coercion with unary +
    s = "42"
    print "+s + 8       :", +s + 8

    # Force string coercion by concatenating empty string
    n = 100
    print "(n \"\") < \"99\":", ((n "") < "99")   # 1 (string compare)

    # Booleans are just numbers: 1 and 0
    result = (5 > 3)
    print "result of 5>3:", result
}

Logical Operators

AWK uses C-style logical operators with short-circuit evaluation. Any non-zero, non-empty value is truthy; 0 and "" are falsy.

OperatorMeaning
&&Logical AND
||Logical OR
!Logical NOT

Create a file named logical.awk:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
BEGIN {
    age = 25
    has_license = 1

    if (age >= 18 && has_license)
        print "Eligible to drive"

    if (age < 13 || age > 65)
        print "Discount applies"
    else
        print "Standard fare"

    # Short-circuit: right side not evaluated if left determines result
    x = 0
    if (x != 0 && (10 / x) > 1)
        print "won't divide by zero — short-circuited"
    else
        print "safely skipped division"

    # Truthiness of values
    print "!0     =", !0       # 1
    print "!\"\"   =", !""     # 1
    print "!\"0\"  =", !"0"    # 0  (non-empty string is truthy!)
    print "!1     =", !1       # 0
}

A famous AWK gotcha: the string "0" is truthy because it is a non-empty string, even though the number 0 is falsy. When in doubt, force the type with +x (numeric) or x "" (string).

String Concatenation: The Invisible Operator

AWK has no explicit string concatenation operator — you simply place expressions next to each other. This is unusual and worth seeing in action.

Create a file named concatenation.awk:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
BEGIN {
    first = "Hello"
    second = "World"

    # Adjacency = concatenation
    greeting = first " " second "!"
    print greeting

    # Mixing numbers and strings — AWK auto-coerces
    n = 42
    label = "answer=" n
    print label

    # Concatenation has LOWER precedence than arithmetic
    # so this works as you'd expect:
    print "sum is " 2 + 3        # "sum is 5"

    # But beware: concatenation is left-associative and tighter than comparison
    a = 1
    b = 2
    # (a b) becomes "12", then compared against "3"
    print "a b > 3 :", (a b > 3)
}

Regular Expression Match Operators

AWK is a text-processing language, so it elevates regex matching to first-class operators: ~ (matches) and !~ (does not match). These are the operators most often used in patterns.

Create a file named regex_ops.awk:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
BEGIN {
    # Build sample data inline so we don't need an input file
    data[1] = "INFO  user logged in"
    data[2] = "ERROR disk full"
    data[3] = "WARN  cache miss"
    data[4] = "ERROR connection refused"
    data[5] = "INFO  request handled"

    for (i = 1; i <= 5; i++) {
        line = data[i]

        if (line ~ /^ERROR/)
            print "error  -> " line
        else if (line !~ /INFO/)
            print "other  -> " line
        else
            print "info   -> " line
    }

    # Regex operators also work in patterns at the top level (see below)
}

# These rules use ~ and !~ implicitly via /regex/ pattern shorthand
# /pattern/ alone is equivalent to:  $0 ~ /pattern/

Conditional (Ternary) Operator

AWK supports the C-style ternary ?: for inline conditional expressions.

Create a file named ternary.awk:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
BEGIN {
    for (n = -2; n <= 2; n++) {
        sign = (n > 0) ? "positive" : (n < 0) ? "negative" : "zero"
        printf "%2d is %s\n", n, sign
    }

    # Combined with the unary + and concatenation
    score = 87
    grade = (score >= 90) ? "A" : (score >= 80) ? "B" : (score >= 70) ? "C" : "F"
    print "score=" score " grade=" grade
}

Operator Precedence

When operators combine, precedence determines the order of evaluation. From highest to lowest, AWK’s most-used operators rank roughly:

  1. ( ) grouping, $ field reference
  2. ++ -- (pre/post)
  3. ^ ** exponentiation (right-associative)
  4. ! +x -x unary
  5. * / %
  6. + -
  7. string concatenation (no symbol)
  8. < <= > >= != ==
  9. ~ !~
  10. &&
  11. ||
  12. ?: ternary
  13. = += -= *= /= %= ^=

Create a file named precedence.awk:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
BEGIN {
    # Exponentiation is right-associative
    print "2 ^ 3 ^ 2 =", 2 ^ 3 ^ 2     # 2^(3^2) = 512, not (2^3)^2 = 64

    # Multiplication before addition
    print "2 + 3 * 4 =", 2 + 3 * 4     # 14

    # Concatenation is lower than arithmetic but higher than comparison
    print "result: " 1 + 2             # "result: 3"

    # Use parentheses when in doubt — they are free
    print ((2 + 3) * 4)                # 20
    print (2 + 3 * 4)                  # 14
}

Running with Docker

Run any of the examples above with the Alpine image bundled with BusyBox AWK:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Pull the image once
docker pull alpine:latest

# Run each example
docker run --rm -v $(pwd):/app -w /app alpine:latest awk -f arithmetic.awk
docker run --rm -v $(pwd):/app -w /app alpine:latest awk -f assignment.awk
docker run --rm -v $(pwd):/app -w /app alpine:latest awk -f comparison.awk
docker run --rm -v $(pwd):/app -w /app alpine:latest awk -f logical.awk
docker run --rm -v $(pwd):/app -w /app alpine:latest awk -f concatenation.awk
docker run --rm -v $(pwd):/app -w /app alpine:latest awk -f regex_ops.awk
docker run --rm -v $(pwd):/app -w /app alpine:latest awk -f ternary.awk
docker run --rm -v $(pwd):/app -w /app alpine:latest awk -f precedence.awk

Expected Output

Output of arithmetic.awk:

a = 17  b = 5
a + b = 22
a - b = 12
a * b = 85
a / b = 3.4
a % b = 2
a ^ b = 1419857
-a    = -17
10 / 3 = 3.33333
int(10/3) = 3

Output of assignment.awk:

start    x = 10
x += 5   x = 15
x -= 3   x = 12
x *= 2   x = 24
x /= 4   x = 6
post  y++ -> 1 after: 2
pre  ++z -> 2 after: 2
counter starts at: 
after counter++ : 1

Output of comparison.awk:

10 > 9       : 1
10 == 10.0   : 1
"10" > "9"   : 0
"abc" < "abd" : 1
+s + 8       : 50
(n "") < "99": 1
result of 5>3: 1

Output of logical.awk:

Eligible to drive
Standard fare
safely skipped division
!0     = 1
!""   = 1
!"0"  = 0
!1     = 0

Output of concatenation.awk:

Hello World!
answer=42
sum is 5
a b > 3 : 1

Output of regex_ops.awk:

info   -> INFO  user logged in
error  -> ERROR disk full
other  -> WARN  cache miss
error  -> ERROR connection refused
info   -> INFO  request handled

Output of ternary.awk:

-2 is negative
-1 is negative
 0 is zero
 1 is positive
 2 is positive
score=87 grade=B

Output of precedence.awk:

2 ^ 3 ^ 2 = 512
2 + 3 * 4 = 14
result: 3
20
14

Key Concepts

  • Division is always floating-point — use int() to truncate toward zero when you need integer behavior.
  • Comparison is type-sensitive: AWK compares numerically when both operands look like numbers, lexicographically otherwise. Force the type with unary + or by concatenating "".
  • String concatenation is invisible — adjacent expressions concatenate, with precedence between arithmetic and comparison. Wrap in parentheses when mixing.
  • "0" is truthy while 0 is falsy. The type-aware truthiness rule trips up almost everyone at least once.
  • Regex operators ~ and !~ are first-class and most often used in patterns: $3 ~ /^[0-9]+$/ { … } is idiomatic AWK.
  • Exponentiation ^ is right-associative: 2 ^ 3 ^ 2 evaluates as 2 ^ (3 ^ 2) = 512.
  • Uninitialized variables behave as 0 in numeric context and "" in string context, which makes counter idioms like count[$1]++ work without explicit initialization.
  • When in doubt, parenthesize — AWK’s precedence rules around concatenation and comparison are subtle, and parentheses cost nothing at runtime.

Running Today

All examples can be run using Docker:

docker pull alpine:latest
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining