GNU Awk (gawk) 5.3.0 (stable as of late 2025) is the primary implementation.

Core Syntax

AWK processes input line by line, executing action blocks when pattern matches. BEGIN and END blocks run before and after file processing, respectively.

# Basic structure: 'pattern { action }'
# Prints every line (default action if none specified)
awk '{ print }' data.txt

# Prints lines containing "error"
awk '/error/ { print }' log.txt

# BEGIN block: executed once before any input is read
# END block: executed once after all input is processed
awk 'BEGIN { print "--- Log Analysis Start ---" } /FAIL/ { count++ } END { print "Total failures:", count }' system.log

Field Handling & Built-in Variables

AWK automatically splits each input line into fields. $0 is the entire line, $1 is the first field, $2 the second, and so on. NF is the number of fields, NR is the current record (line) number, FS is the field separator (default space/tab), OFS is the output field separator (default space).

# Print the second and first fields, separated by a comma
awk '{ print $2, $1 }' names.txt

# Print the last field of each line
awk '{ print $NF }' data.csv

# Change field separator to comma using -F option
awk -F',' '{ print $1, $3 }' data.csv

# Change field separator within the script (BEGIN block is ideal)
awk 'BEGIN { FS=":"; OFS=" -> " } { print $1, $3 }' /etc/passwd

# Print line number and the entire line
awk '{ print NR, $0 }' file.txt

# Process only lines with at least 3 fields
awk 'NF >= 3 { print $1, $NF }' data.log

Conditional Logic & Loops

AWK supports if/else, for, and while loops for flow control. next skips to the next input record, exit terminates processing.

# If-else statement: check a condition on a field
awk '{
    if ($3 > 100) {
        print "High value:", $0
    } else {
        print "Normal value:", $0
    }
}' metrics.txt

# For loop: iterate through fields
awk '{
    for (i = 1; i <= NF; i++) { # Loop from first field to last
        print "Field", i, ":", $i
    }
}' single_line.txt

# While loop: example for specific conditions (less common than for)
awk '{
    i = 1
    while (i <= NF && length($i) < 5) { # Process fields while length is less than 5
        print "Short field:", $i
        i++
    }
}' words.txt

# 'next' statement: skip remaining actions for current record
awk '/^#/ { next } { print $0 }' config.ini # Skip comment lines

# 'exit' statement: stop processing immediately
awk '/ERROR/ { print "Found error, exiting."; exit } { print $0 }' log.txt

Functions & Arrays

AWK supports user-defined functions and powerful associative arrays (hash maps).

# User-defined function: calculate average
awk '
function average(a, b) { # Define a function 'average'
    return (a + b) / 2
}
{
    avg = average($1, $2) # Call the function
    print $1, $2, avg
}' numbers.txt

# Associative arrays: count occurrences of field values
awk '{
    count[$1]++ # Increment count for the value of the first field
}
END {
    for (item in count) { # Iterate through array keys
        print item, count[item]
    }
}' access.log

# Associative arrays for summing values by key
awk '{
    sum[$1] += $2 # Add second field to sum for key (first field)
}
END {
    for (key in sum) {
        print key, sum[key]
    }
}' sales.csv

Output Formatting

The printf function provides C-style formatted output, offering more control than print.

# printf for formatted output
awk '{
    printf "Item: %-10s Price: $%5.2f Quantity: %d\n", $1, $2, $3
}' inventory.txt

# Example with padding and precision
# %-10s: left-justified string, 10 chars wide
# %5.2f: float, 5 total width (including decimal), 2 decimal places
# %d: integer

Real-world Log Processing

AWK excels at parsing structured log files.

# Example: Extract IP, timestamp, and request from Apache access logs
# Log format: 192.168.1.1 - - [29/Dec/2025:10:00:00 +0000] "GET /index.html HTTP/1.1" 200 1234
awk -F'[][]' '{ # Split by square brackets
    ip = $1; sub(/ - - $/, "", ip) # Clean up IP field
    timestamp = $2 # Timestamp is in second field
    request = $3; sub(/^"|"$ /, "", request) # Clean up request field
    print "IP:", ip, "Time:", timestamp, "Request:", request
}' access.log

# Example: Sum bytes transferred by IP
awk '{
    ip = $1
    bytes = $NF # Last field is bytes transferred
    if (bytes ~ /^[0-9]+$/) { # Ensure bytes is a number
        total_bytes[ip] += bytes
    }
}
END {
    print "--- Bytes Transferred by IP ---"
    for (addr in total_bytes) {
        printf "%-15s %10d bytes\n", addr, total_bytes[addr]
    }
}' access.log

Performance Considerations

For very large files, performance matters.

# Pre-filter with grep for massive files to reduce AWK's workload
# This is often faster than AWK's pattern matching on its own for simple regex
grep "specific_pattern" large_file.log | awk '{ print $1, $NF }'

# Use 'next' early to avoid unnecessary processing
# If a line doesn't meet initial criteria, skip it immediately
awk '{
    if ($1 == "SKIP") { next } # Skip lines starting with "SKIP"
    # ... rest of complex processing ...
    print $0
}' data.txt

# Avoid unnecessary regex matching in loops
# Pre-compile regex if possible (gawk specific, `~` operator is fast enough for most)
# For very complex patterns, consider using `match()` and `RSTART`/`RLENGTH`

Gotchas & Best Practices

  • FS vs -F: Setting FS in BEGIN block is generally cleaner and more robust than -F for complex separators.
  • Default Action: If no action is specified for a pattern, print $0 is the default.
  • Quoting: Shell expansion can interfere. Always single-quote AWK scripts to prevent shell interpretation of $, *, etc.
  • Variable Scope: All variables are global by default. Use parameter lists in user-defined functions to declare local variables (e.g., function my_func(arg, local_var1, local_var2)).
  • Empty Fields: When FS is a single character, consecutive separators result in empty fields (e.g., a,,b with FS="," gives $2=""). If FS is a regex, multiple separators are treated as one.
  • Performance with printf: printf can be slightly slower than print due to formatting overhead, but usually negligible.

Quick Reference

  • Command: awk 'script' file(s) or awk -f script_file file(s)
  • Built-in Variables:
    • $0: Entire line
    • $1, $2, ...: Fields
    • NF: Number of fields
    • NR: Record (line) number
    • FS: Input Field Separator (default: whitespace)
    • OFS: Output Field Separator (default: space)
    • RS: Record Separator (default: newline)
    • ORS: Output Record Separator (default: newline)
    • FILENAME: Current input filename
  • Patterns: /regex/, expression, BEGIN, END, pattern1, pattern2 (range)
  • Actions: { statements }
  • Control Flow: if/else, for, while, next, exit
  • Functions: length(), sub(), gsub(), split(), substr(), index(), match(), sprintf(), system(), atan2(), cos(), sin(), exp(), log(), sqrt(), rand(), srand(), int(), toupper(), tolower()
  • Operators: Arithmetic (+ - * / % ^), Comparison (== != < > <= >=), Logical (&& || !), Assignment (= += -= *= /= %= ^=), Concatenation (space)
  • Version: GNU Awk (gawk) 5.3.0 (as of 2025-12-29)

References

  1. GNU Awk User’s Guide - The definitive guide for gawk.
  2. AWK - A Tutorial and Introduction - A comprehensive, classic tutorial.
  3. The AWK Programming Language (Book) - The original book by Aho, Weinberger, Kernighan.

This page is AI-assisted. References official documentation.