awk Cheatsheet
Output Formatting
Use this awk reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
print versus printf
print joins its arguments with OFS and appends ORS. printf writes exactly
what the format says, including no trailing newline unless you add \n.
awk '{ print $1, $2 }' # joined by OFS, newline added awk '{ print $1 $2 }' # concatenated, no separator awk '{ printf "%s=%s\n", $1, $2 }' # you control everything awk 'BEGIN{ printf "no newline" }' # output ends mid-line
- print with no arguments means print $0.
- The comma is what inserts OFS. Omit it and you get concatenation.
- printf needs parentheses only when you also redirect:
printf("%s\n", $1) > "out.txt".
Format specifiers
| Spec | Prints |
|---|---|
%d %i | integer, truncating the fraction |
%o %x %X | octal, lower and upper hex |
%u | unsigned decimal |
%c | one character. A number becomes that character code, a string its first char |
%s | string |
%e %E | scientific, 1.234500e+04 |
%f | fixed point, 6 decimals by default |
%g %G | shorter of %e and %f, trailing zeros dropped |
%% | a literal percent sign |
| Modifier | Effect |
|---|---|
%-10s | left justify in width 10 |
%10s | right justify in width 10 |
%.3f | precision, 3 decimals |
%.5s | truncate a string to 5 characters |
%010.3f | zero-pad to total width 10 |
%+d | always show a sign |
% d | space where a plus would go |
%*d | width taken from the next argument |
awk 'BEGIN{ printf "%5.2f|%-5s|%05d|%x|%e\n", 3.14159, "ab", 42, 255, 12345 }' # 3.14|ab |00042|ff|1.234500e+04 awk 'BEGIN{ printf "%*d|\n", 6, 42 }' # 42| awk 'BEGIN{ printf "%c%c\n", 72, "int" }' # Hi awk 'BEGIN{ printf "100%%\n" }' # 100%
Too few arguments is a fatal error in both macOS awk and gawk (
not enough args in printf). Too many are silently ignored, with no warning, so a shifted format string fails quietly in only one direction.
Aligned tables
# a fixed-width report with a header rule awk 'BEGIN{ printf "%-12s %8s %6s\n", "NAME", "BYTES", "PCT" printf "%-12s %8s %6s\n", "------------", "--------", "------" } { printf "%-12.12s %8d %5.1f%%\n", $1, $2, 100 * $2 / 1024 }' sizes.txt
# right-align a numeric column whose width you learn on the fly awk '{ v[NR]=$2; k[NR]=$1; if (length($2) > w) w = length($2) } END { for (i=1;i<=NR;i++) printf "%-10s %*s\n", k[i], w, v[i] }' sizes.txt
When the columns come from the data rather than a format string, column -t is
usually less work:
awk 'BEGIN{OFS="\t"} { $1=$1; print }' data.txt | column -t -s $'\t'
Separators: OFS and ORS
# tab-separated output from comma-separated input awk 'BEGIN{ FS=","; OFS="\t" } { $1=$1; print }' in.csv # one long comma-joined line awk 'BEGIN{ ORS="," } { print $1 } END{ printf "\n" }' in.txt # blank line between records awk 'BEGIN{ ORS="\n\n" } { print }' in.txt
The $1=$1 is required. OFS is applied when awk rebuilds $0, and printing
an untouched record uses the original bytes. Touching any field forces the rebuild.
Number formatting gotchas
awk 'BEGIN{ print 0.1 + 0.2 }' # 0.3, OFMT hides the float error awk 'BEGIN{ printf "%.17f\n", 0.1 + 0.2 }' # 0.30000000000000004 awk 'BEGIN{ print 2^53 + 1 }' # 9007199254740992, precision lost awk 'BEGIN{ print 1234567.891 }' # 1.23457e+06, OFMT is %.6g awk 'BEGIN{ printf "%.3f\n", 1234567.891 }' # 1234567.891
- awk numbers are C doubles. Integers above 2^53 are not exact, and big IDs read as
numbers will silently round. Keep them as strings ($1 "").
- print sends a non-integral number through OFMT (%.6g), which is why
1234567.891 prints as 1.23457e+06. Values that are whole numbers bypass it and
print in full. Use printf "%d" or printf "%.15g" when the digits matter.
- %d on a value beyond a 64-bit integer is undefined. gawk warns, macOS awk does
not.
- gawk has --bignum for arbitrary precision. macOS awk and mawk do not.
Redirecting output
| Form | Effect |
|---|---|
print > "f" | truncate f on the first write, then append |
print >> "f" | append, never truncates |
print | "cmd" | pipe into a shell command |
print > "/dev/stderr" | stderr (gawk always, macOS awk via the real device) |
close("f") | flush and release the handle |
# split by key, closing handles so you do not run out of descriptors awk '{ f = "part_" $1 ".txt"; print >> f; open[f]=1 } END { for (k in open) close(k) }' data.txt # sort a section without leaving awk awk '/^BEGIN/,/^END/ { print | "sort" } END { close("sort") }' file # warnings to stderr, data to stdout awk 'NF != 3 { print "bad line " NR > "/dev/stderr"; next } { print $2 }' d.txt
Parenthesize a computed target. print > "out" i ".txt" is a syntax error in
macOS awk and is misparsed by gawk. Write print > ("out" i ".txt"), or put the name
in a variable first. Two different strings mean two different files, and each stays
open until you close() it.