awk
Skill7 starsChanged 10 months agoMITView on GitHub
Expert GNU awk (gawk) one-liner generation and transformation. Use this skill whenever the user asks to process text fields, extract columns, compute sums or aggregates, filter structured output, reformat CSV/TSV, parse logs, generate reports, or do any record/field processing task. Trigger on keywords like "awk", "extract column", "sum a field", "count occurrences", "print field N", "filter by column", "reformat output", "aggregate log data", "process CSV", "TSV", or any request that maps to a field-oriented text transformation. When in doubt, use this skill — awk is often the right tool when sed isn't enough.
In this repository30 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- apple-cktool-jsSkill
- apple-cktoolSkill
- audit-training-experimentSkill
- close-out-ml-experimentSkill
- compare-models-blindlySkill
- conventional-commitsSkill
- design-resumable-model-evaluationSkill
- gogopowermanagerSkill
- ios-design-reviewSkill
- mikrotik-routerosSkill
- obsidian-dailySkill
- orbstack-cliSkill
- package-private-ml-artifactsSkill
- prepare-training-corpusSkill
- proxmox-adminSkill
- review-ios-ui-apple-higSkill
- review-training-data-qualitySkill
- run-hugging-face-training-smokeSkill
- sedSkill
- select-and-verify-best-checkpointSkill
- send-to-minionSkill
- swift-reviewSkill
- technical-writerSkill
- tmuxinatorSkill
- topydoSkill
- unhobble-agent-contextSkill
- validate-structured-model-outputSkill
- write-a-promptSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 4 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 16
All output assumes gawk (awk --version shows GNU Awk).
- Distinctive: line 30
Chain with pipes: when awk alone isn't the cleanest tool.
- Distinctive: line 300
When responding to an awk request:
- Distinctive: line 303
Add a one-line comment per non-obvious part.
- Distinctive: line 304
If the task fits a multi-step pipeline better, show that pipeline.
- Very specific: line 305
If the task is better served by jq, mlr (miller), python, or perl, say so briefly and optionally show that alternative too.
- Very specific: line 312
Portable awk has no in-place editing: Use > tmp && mv tmp original unless you intentionally depend on gawk's -i inplace extension.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
GNU awk (gawk) Skill
All output assumes gawk (awk --version shows GNU Awk). POSIX awk
compatibility is not a goal; gawk extensions are used freely where they help.
Core Principles
- Prefer one-liners. Multi-line awk scripts only when a one-liner becomes unreadable.
- Use
-Fto set the field separator explicitly. Never assume space. - Dry-run friendly by default. awk reads and prints; it never edits files
in-place. Redirect explicitly (
> out && mv out in) when the user wants in-place behavior. - Use
BEGIN/ENDblocks for setup and summary output. - Chain with pipes when awk alone isn't the cleanest tool.
- Never use awk to parse JSON or XML. Redirect to
jq/xmllintand say why.
Mental Model
awk 'BEGIN { setup } /pattern/ { action } END { summary }' file- awk reads input line by line (records, split by
RS, default\n). - Each record is split into fields by
FS(default: any whitespace). $0= entire record.$1,$2, ...$NF= individual fields.NF= number of fields.NR= current record number.FNR= record number within current file.
Flags
| Flag | Meaning |
-F SEP | Set field separator (string or regex) |
-v VAR=VAL | Set a variable before execution |
-f FILE | Read awk program from a file |
--sandbox | Disable system(), getline, pipe (safe) |
Command Quick Reference
Print specific fields
# Print fields 1 and 3
awk '{print $1, $3}' file.txt
# Print last field
awk '{print $NF}' file.txt
# Print second-to-last
awk '{print $(NF-1)}' file.txt
# Custom output separator
awk '{print $1 "," $2}' file.txtFilter lines
# Lines where field 3 > 100
awk '$3 > 100' file.txt
# Lines matching a regex
awk '/error/' file.txt
# Lines where field 2 matches a pattern
awk '$2 ~ /timeout/' file.txt
# Negate match
awk '$2 !~ /debug/' file.txt
# Multiple conditions
awk '$1 == "GET" && $9 >= 500' access.logAggregation
# Sum a column
awk '{sum += $3} END {print sum}' file.txt
# Count matching lines
awk '/error/ {count++} END {print count}' file.txt
# Average
awk '{sum += $2; n++} END {print sum/n}' file.txt
# Min / max
awk 'NR==1 || $3 < min {min=$3} END {print min}' file.txt
awk 'NR==1 || $3 > max {max=$3} END {print max}' file.txtFrequency / histogram
# Count occurrences of each value in field 1
awk '{count[$1]++} END {for (k in count) print count[k], k}' file.txt | sort -rn
# Top 10 IPs in nginx log
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
# Pure awk alternative:
awk '{c[$1]++} END {for (ip in c) print c[ip], ip}' access.log | sort -rn | head -10Field reformat / transform
# Swap fields 1 and 2
awk '{print $2, $1}' file.txt
# Prepend a string to field 1
awk '{$1 = "prefix_" $1; print}' file.txt
# Change field separator in output (OFS)
awk 'BEGIN{OFS=","} {print $1,$2,$3}' file.txt
# Remove a field (shift left from field 3)
awk '{out=""; for (i=1;i<=NF;i++) if (i!=2) out = out (out?OFS:"") $i; print out}' file.txtLine ranges
# Print lines 5 to 15
awk 'NR>=5 && NR<=15' file.txt
# Print between two patterns (inclusive)
awk '/START/,/END/' file.txt
# Skip the header line
awk 'NR > 1' file.txt
# Print only the header
awk 'NR == 1' file.txtCSV / TSV processing
# TSV: print columns 1 and 4
awk -F'\t' '{print $1, $4}' data.tsv
# CSV (simple, no quoted commas): sum column 3
awk -F',' 'NR>1 {sum+=$3} END {print sum}' data.csv
# Add a computed column to CSV
awk -F',' 'BEGIN{OFS=","} NR>1 {$4=$2*$3; print}' data.csv
# Filter CSV rows where column 2 > 50
awk -F',' '$2 > 50' data.csv
# Convert TSV to CSV
awk 'BEGIN{FS="\t"; OFS=","} {$1=$1; print}' data.tsvFor CSV with quoted fields containing commas, use
gawkwith a proper CSV library or switch tomiller(mlr) /csvkit.
Log processing
# Extract HTTP 5xx lines from nginx access log
awk '$9 >= 500 && $9 < 600' access.log
# Sum bytes transferred (field 10) per status code (field 9)
awk '{bytes[$9]+=$10} END {for (s in bytes) print s, bytes[s]}' access.log | sort
# Requests per minute (timestamp in field 4, format [DD/Mon/YYYY:HH:MM:SS])
awk '{match($4, /[0-9]{2}\/[A-Za-z]+\/[0-9]{4}:[0-9]{2}:[0-9]{2}/, m); c[m[0]]++}
END {for (t in c) print t, c[t]}' access.log | sort
# Strip log prefix, print only message
awk '{$1=$2=$3=""; print substr($0,4)}' app.logMulti-file processing
# Print filename alongside each line
awk '{print FILENAME, $0}' *.log
# Process file 1 as a lookup table, file 2 as data
awk 'NR==FNR {map[$1]=$2; next} {print $0, map[$1]}' lookup.txt data.txtIn-place editing
# Portable awk has no in-place edit; prefer a temp file
awk '{gsub(/foo/, "bar"); print}' file.txt > file.tmp && mv file.tmp file.txt
# gawk-only in-place edit
gawk -i inplace '{gsub(/foo/, "bar"); print}' file.txt
# All .rb files
for f in src/**/*.rb; do
awk '{gsub(/OldClass/, "NewClass"); print}' "$f" > "$f.tmp" && mv "$f.tmp" "$f"
doneBuilt-in Functions
String
| Function | Description |
length(s) | String length |
substr(s, start, len) | Substring (1-indexed) |
index(s, t) | Position of t in s (0 = not found) |
split(s, arr, sep) | Split s into arr by sep, returns count |
gsub(re, rep, s) | Global replace in s (default: $0) |
sub(re, rep, s) | First replace in s |
match(s, re, arr) | Match re in s; fills arr with groups |
sprintf(fmt, ...) | Format string (like printf) |
tolower(s) / toupper(s) | Case conversion |
gensub(re, rep, how, s) | gawk: replace with back-references (\1) |
Math
| Function | Description |
int(x) | Truncate to integer |
sqrt(x) | Square root |
log(x) / exp(x) | Natural log / e^x |
sin(x) / cos(x) | Trig (radians) |
rand() | Random [0,1) |
srand(seed) | Seed RNG |
gawk Extensions Worth Knowing
# OFMT: control float output precision
awk 'BEGIN{OFMT="%.2f"} {print $1 * 1.15}' prices.txt
# Pipe to a command per line
awk '{print $0 | "mail -s alert ops@example.com"}' alerts.txt
# Time functions
awk 'BEGIN{print strftime("%Y-%m-%d", systime())}'
# Two-way pipe (gawk only): close the writer before reading from sort
awk 'BEGIN{cmd="sort"} {print $0 |& cmd} END{close(cmd, "to"); while ((cmd |& getline line) > 0) print line}' file.txt
# Built-in CSV parsing (gawk 5.3+)
gawk --csv '{print $2}' data.csv
# Legacy/simple CSV only: FPAT misses empty fields and escaped quotes
awk 'BEGIN{FPAT="([^,]+)|(\"[^\"]+\")"} {print $2}' data.csvCombining with Other Tools
# awk + sort: frequency table
awk '{print $1}' file.txt | sort | uniq -c | sort -rn
# awk + sed: awk extracts, sed cleans
awk '/error/ {print $5}' app.log | sed 's/[^a-z0-9]//g'
# awk + xargs: act on extracted values
awk '$3 > 1000 {print $1}' jobs.txt | xargs kill
# awk as a replacement for cut + grep pipeline
# Instead of: grep 'GET' access.log | cut -d' ' -f7
awk '$6 ~ /GET/ {print $7}' access.logOutput Format
When responding to an awk request:
- Show the one-liner in a code block, ready to copy-paste.
- Add a one-line comment per non-obvious part.
- If the task fits a multi-step pipeline better, show that pipeline.
- If the task is better served by
jq,mlr(miller),python, orperl, say so briefly and optionally show that alternative too.
Gotchas
- Portable awk has no in-place editing. Use
> tmp && mv tmp originalunless you intentionally depend on gawk's-i inplaceextension. - Field assignment triggers rebuild of
$0usingOFS. SetOFSinBEGINif you rely on this. - Arrays are associative only (hash maps). There are no integer-indexed arrays
with guaranteed order; iterate with
for (k in arr)(order is undefined). Use a separate key list +asort()/asorti()(gawk) when order matters. - Rebuilding vs re-splitting. Assigning to a field rebuilds
$0from fields usingOFS($1=$1is the common idiom). Assigning to$0, orsub()/gsub()on$0, re-splits fields using the currentFS. - Regex constants vs strings.
/foo/is a regex literal;"foo"is a string.$1 ~ /foo/is correct;$1 ~ "foo"also works but avoids the literal syntax. - Integer division.
5/2returns2.5in awk (unlike shell). Useint(5/2)for truncation. - macOS ships BSD/one-true-awk, not gawk.
gawkmust be installed via Homebrew.FPAT,gensub(),strftime(), and|&are gawk-only.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

