====== awk ====== A tiny language for column/record processing. Pattern: ''pattern { action }'' per line. Ubuntu ships **mawk** (fast, smaller feature set) : ''sudo apt install gawk'' gets you the full GNU dialect (''gensub'', ''strftime'', ''mktime'', ''asort'', ''BEGINFILE''). ===== Model ===== awk '{print $1}' # $0=whole line, $1..$NF=fields, NF=count awk 'NR==5' # NR=line number (bare pattern = print) awk -F: '{print $1}' /etc/passwd # field separator awk -F: -v OFS='|' '{print $1,$3}' # output separator Built-ins: ''NR'' record#, ''NF'' field count, ''FS''/''OFS''/''RS''/''ORS'', ''FILENAME'', ''$0'', ''$1..$NF'', ''$(NF-1)'' (second-to-last). ===== Patterns ===== awk '$3 > 100' # numeric compare awk '$1 ~ /foo/' # field matches regex (== !~ for not) awk '/start/,/end/' # range pattern awk 'NR>=10 && NR<=20' awk 'length($0) > 80' # long lines awk 'END{print}' # last line ===== BEGIN / END: headers, totals ===== awk 'BEGIN{FS=":"} {s+=$3} END{print "total:",s}' /etc/passwd ps aux | awk '{m+=$6} END{printf "%.1f MB\n", m/1024}' # total RSS ===== Associative arrays: the main feature ===== awk '{count[$1]++} END{for(k in count) print k, count[k]}' # histogram awk '{seen[$0]++} !seen[$0]-1' ... # just: awk '!seen[$0]++' dedupes awk '{sum[$1]+=$2} END{for(k in sum) print k":"sum[k]}' # group+sum ===== String functions ===== length(x) substr(s,i,n) index(s,t) tolower(s) toupper(s) split(s,a,sep) # array from string gsub(re,rep,str) # global replace IN the string (returns count) sub(re,rep,str) # first only sprintf(fmt,...) # returns formatted (printf prints) match(s,re) # sets RSTART/RLENGTH awk '{gsub(/"/,""); print}' csvish.txt awk '{split($1,a,"."); print a[1]}' # first dotted part awk '{printf "%-20s %6.2f\n", $1, $2}' # aligned columns ===== Multiline / CSV-ish handling ===== awk -v RS='' '{print NR": "$0}' f # paragraph mode (blank-line records) awk -F'";"' '{print $2}' file # crude quoted-CSV: real CSV → miller ===== Recipes ===== ps aux | awk '$3>5 {print $2, $3, $11}' # processes >5% CPU df -h | awk 'NR>1 && $5+0>80 {print $6,$5}' # mounts over 80% awk '{s[$1]++} END{for(x in s) print s[x],x}' access.log | sort -rn | head awk 'NR==FNR{a[$1]=1;next} !($1 in a)' a.txt b.txt # lines in b not in a awk '{print $NF}' # last field seq 100 | awk '{sum+=$1} END{print sum/NR}' # mean ===== Gotchas ===== * Fields are **1-indexed**, ''$0'' is the whole line. * ''-F'' takes a regex: ''-F'[,:]''' splits on either. * String vs number: ''$1 == "5"'' string compare, ''$1 == 5'' numeric. * ''print'' adds ORS (newline); ''printf'' doesn't. * mawk lacks ''gensub''/''strftime'': install ''gawk'' if a script needs them. ===== See Also ===== * [[terminal:scripting:start|Scripting Index]] * [[terminal:tools:start|CLI Tools]] * [[terminal:start|Return to terminal]] * [[start|Return to wiki home]]