awk Patterns

awk patterns I’ve actually used. Every entry has a date and context.

2026-03-05: PEM Certificate Chain Split

Problem: Need to extract individual certs from a chain file

Context: ISE certificate deployment, splitting chain.pem into leaf/issuing/root

The Fix:

# Extract first cert (leaf)
awk '/-----BEGIN CERTIFICATE-----/{n++} n==1' chain.pem > leaf.pem

# Extract second cert (issuing CA)
awk '/-----BEGIN CERTIFICATE-----/{n++} n==2' chain.pem > issuing-ca.pem

# Extract third cert (root CA)
awk '/-----BEGIN CERTIFICATE-----/{n++} n==3' chain.pem > root-ca.pem

How it works: Counter n increments each time BEGIN CERTIFICATE is seen. n==1 prints only while counter equals 1 (first cert block).

Worklog: WRKLOG-2026-03-05


2026-03-05: Field Separator for Dots

Problem: Split IP address or FQDN by dots

Context: Network diagnostics, parsing ip command output

The Fix:

# WRONG: dot is regex "any char"
awk -F'.' '{print $1}' file

# RIGHT: escape the dot
awk -F'\\.' '{print $1}' file

# ALSO RIGHT: use bracket (more readable)
awk -F'[.]' '{print $1}' file

Rule: -F takes a regex. Dots must be escaped or bracketed.

Worklog: WRKLOG-2026-03-05


2026-03-05: Pipe Field Separator

Problem: Parse pipe-delimited output

Context: Parsing switch/router show commands

The Fix:

# WRONG: pipe is regex alternation
awk -F'|' '{print $1}' file

# RIGHT: escape or bracket
awk -F'\\|' '{print $1}' file
awk -F'[|]' '{print $1}' file

Worklog: WRKLOG-2026-03-05


2026-03-01: Line Range with Buffer

Problem: Show first 5 and last 5 lines of a file with line numbers

Context: Quick file inspection without loading entire file

The Fix:

awk 'NR<=5 {print NR": "$0; next} {buf[NR]=$0} END {print "..."; for(i=NR-4;i<=NR;i++) print i": "buf[i]}' file

How it works: - First 5 lines: print immediately with line number - Remaining lines: store in buffer array (overwrites, keeping only recent) - END: print last 5 from buffer

Worklog: WRKLOG-2026-03-01


2026-03-05: Extract IP from Command Output

Problem: Get IP address from ip addr output

Context: Network diagnostics, scripting

The Fix:

# Get IP with CIDR
ip -4 addr show eth0 | awk '/inet/{print $2}'

# Get just IP without CIDR
ip -4 addr show eth0 | awk '/inet/{split($2,a,"/"); print a[1]}'

# Get default route interface
ip route | awk '/default/{print $5}'

Worklog: WRKLOG-2026-03-05


2026-04-05: find + awk — Filter vs Find-Native

Problem: Filter find output by filename pattern using awk

Context: Searching for CLAUDE.md in dots-quantum repo during opencode config audit. Hand-typed all variants to build muscle memory.

The Fix:

# WORKS but wasteful — awk filters what find already knows
find . -type f -name "*.md" | awk '/CLAUDE/'

# RIGHT — push filter into find
find . -type f -name "CLAUDE.md"

# ALSO RIGHT — partial match on filename
find . -type f -name "*CLAUDE*.md"

# RIGHT — when filtering on path components
find . -type f -path "*CLAUDE*" -name "*.md"

# WHEN awk IS right — filtering on CONTENT, not filename
find . -type f -name "*.md" -exec awk '/^## Role:/{print FILENAME": "$0}' {} +

Rule: If awk is only doing // (pattern match) on filenames, push that into find -name or -path. Reserve find -exec awk for content filtering or field extraction — that’s where the combination actually earns its complexity.

Worklog: WRKLOG-2026-04-05