这是 GNU awk 的单页快速参考备忘单,其中涵盖了常用的 awk
表达式和命令。
入门 试试 该程序可用于选择文件中的特定记录并对其执行操作
1 $ awk -F: '{print $1, $NF}' /etc/passwd
-
-
-
-F:
冒号作为分隔符
{...}
awk 程序
print
打印当前记录
$1
第一个字段
$NF
最后一个字段
/etc/passwd
输入数据文件
Awk 程序 1 2 3 4 5 BEGIN {<初始化>} <pattern 1> {<计划动作>} <pattern 2> {<计划动作>} ... END {< 最后的动作 >}
示例 1 2 3 4 5 awk ' BEGIN { print "\n>>>Start" } !/(login|shutdown)/ { print NR, $0 } END { print "<<<END\n" } ' /etc/passwd
变量 1 2 3 4 5 6 7 8 9 $1 $2 /$(NF-1) $3 /$NF ▼ ▼ ▼ ┌──────┬──────────────┬───────┐ $0 /NR ▶ │ ID │ WEBSITE │ URI │ ├──────┼──────────────┼───────┤ $0 /NR ▶ │ 1 │ baidu.com │ awk │ ├──────┼──────────────┼───────┤ $0 /NR ▶ │ 2 │ google.com │ 25 │ └──────┴──────────────┴───────┘
1 2 3 4 5 6 7 8 # 第一个和最后一个字段 awk -F: '{print $1,$NF}' /etc/passwd # 带行号 awk -F: '{print NR, $0}' /etc/passwd # 倒数第二个字段 awk -F: '{print $(NF-1)}' /etc/passwd # 自定义字符串 awk -F: '{print $1 "=" $6}' /etc/passwd
查看: Awk 变量
Awk 程序示例 1 2 3 4 5 6 7 8 awk 'BEGIN {print "hello world"}' # 打印 "hello world" awk -F: '{print $1}' /etc/passwd # -F: 指定字段分隔符 # /pattern/ 仅对匹配的模式执行操作 awk -F: '/root/ {print $1}' /etc/passwd # BEGIN 块在开始时执行一次 awk -F: 'BEGIN { print "uid"} { print $1 }' /etc/passwd # END 块在最后执行一次 awk -F: '{print $1} END { print "-done-"}' /etc/passwd
条件 1 awk -F: '$3>30 {print $1}' /etc/passwd
查看: Conditions 条件
生成 1000 个空格 1 2 3 4 5 awk 'BEGIN{ while (a++ < 1000) s=s " "; print s }'
查看: Loops
数组 Arrays 1 2 3 4 5 6 7 awk 'BEGIN { fruits["mango"] = "yellow"; fruits["orange"] = "orange" for(fruit in fruits) { print fruit " 的颜色是 " fruits[fruit] } }'
查看: Awk 数组
函数 Functions 1 2 3 4 5 6 # => 5 awk 'BEGIN{print length("hello")}' # => HELLO awk 'BEGIN{print toupper("hello")}' # => hel awk 'BEGIN{print substr("hello", 1, 3)}'
查看: Functions
Awk 变量 内置变量
:-
:-
$0
全线
$1, $2...$NF
第一个,第二个……最后一个字段
NR
记录总数(N
umber of R
ecords)
NF
N个字段(N
number of F
ields)
OFS
O
utput F
ield S
eparator 输出字段分隔符 (default “ “)
FS
input F
ield S
eparator 输入字段分隔符 (default “ “)
ORS
O
utput R
ecord S
eparator 输出记录分隔符 (default “\n”)
RS
input R
ecord S
eparator 输入记录分隔符 (default “\n”)
FILENAME
文件名
表达式
:-
:-
$1 == "root"
第一个字段等于根
{print $(NF-1)}
倒数第二个字段
NR!=1{print $0}
从第 2 条记录开始
NR > 3
从第 4 条记录开始
NR == 1
第一次记录
END{print NR}
总记录
BEGIN{print OFMT}
输出格式
{print NR, $0}
行号
{print NR " " $0}
行号(选项卡)
{$1 = NR; print}
用行号替换第一个字段
$NF > 4
最后一个字段 > 4
NR % 2 == 0
甚至记录
NR==10, NR==20
记录 10 到 20
BEGIN{print ARGC}
总 arguments
ORS=NR%5?",":"\n"
连接记录
示例 打印总和和平均值
1 2 3 awk -F: '{sum += $3} END { print sum, sum/NR } ' /etc/passwd
打印参数
1 2 3 awk 'BEGIN { for (i = 1; i < ARGC; i++) print ARGV[i] }' a b c
输出字段分隔符为逗号
1 2 awk 'BEGIN { FS=":";OFS=","} {print $1,$2,$3,$4}' /etc/passwd
匹配位置
1 2 3 awk 'BEGIN { if (match("One Two Three", "Tw")) print RSTART }'
匹配时长
1 2 3 awk 'BEGIN { if (match("One Two Three", "re")) print RLENGTH }'
仅限 GNU awk
:-
:-
ENVIRON
环境变量
IGNORECASE
忽略大小写
CONVFMT
转换格式
ERRNO
系统错误
FIELDWIDTHS
固定宽度字段
环境变量
:-
:-
ARGC
数字或参数
ARGV
参数数组
FNR
文件记录数(F
ile N
umber of R
ecords)
OFMT
数字格式 (default “%.6g”)
RSTART
字符串中的位置
RLENGTH
比赛时长
SUBSEP
多维数组分隔符 (default “\034”)
ARGIND
参数索引
定义变量 1 2 3 awk -v var1="Hello" -v var2="Wold" ' END {print var1, var2} ' </dev/null
使用 shell 变量 1 2 awk -v varName="$PWD" ' END {print varName}' </dev/null
Awk 运算符 运算符
:-
:-
{print $1}
第一个字段
$2 == "foo"
等于
$2 != "foo"
不等于
"foo" in array
在数组中
正则表达式
:-
:-
/regex/
行匹配
!/regex/
行不匹配
$1 ~ /regex/
字段匹配
$1 !~ /regex/
字段不匹配
更多条件
:-
:-
($2 <= 4 || $3 < 20)
或者
($1 == 4 && $3 < 20)
和
运算符 算术运算
速记作业
比较运算符
示例 1 2 3 4 awk 'BEGIN { if ("foo" ~ "^fo+$") print "Fooey!"; }'
不匹配 1 2 3 4 awk 'BEGIN { if ("boo" !~ "^fo+$") print "Boo!"; }'
如果在数组中 1 2 3 4 5 6 awk 'BEGIN { assoc["foo"] = "bar"; assoc["bar"] = "baz"; if ("foo" in assoc) print "Fooey!"; }'
Awk 函数 常用功能
函数
描述
index(s,t)
字符串 s
中出现字符串 t
的位置,如果未找到则为 0
length(s)
字符串 s
的长度(如果没有 arg
,则为 $0
)
rand
0
到 1
之间的随机数
substr(s,index,len)
返回从索引开始的 s
的 len-char
子字符串(从 1
开始计数)
srand
为 rand
设置种子并返回之前的种子
int(x)
将 x
截断为整数值
split(s,a,fs)
将字符串 s
拆分为数组 a
由 fs
拆分,返回 a
的长度
match(s,r)
字符串 s
中出现正则表达式 r
的位置,如果未找到,则为 0
sub(r,t,s)
将 t
替换为字符串 s
中第一次出现的正则表达式 r
(如果未给出 s
,则替换为 $0
)
gsub(r,t,s)
用 t
替换字符串 s
中所有出现的正则表达式 r
system(cmd)
执行cmd并返回退出状态
tolower(s)
字符串 s
转小写
toupper(s)
字符串 s
转大写
getline
将 $0
设置为当前输入文件中的下一个输入记录
用户定义函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 awk ' # 返回最小数量 function find_min(num1, num2){ if (num1 < num2) return num1 return num2 } # 返回最大数量 function find_max(num1, num2){ if (num1 > num2) return num1 return num2 } # 主功能 function main(num1, num2){ result = find_min(num1, num2) print "Minimum =", result result = find_max(num1, num2) print "Maximum =", result } # 脚本执行从这里开始 BEGIN { main(10, 60) } '
Awk 数组 带索引的数组 1 2 3 4 5 6 7 awk 'BEGIN { arr[0] = "foo"; arr[1] = "bar"; print(arr[0]); # => foo delete arr[0]; print(arr[0]); # => "" }'
带键的数组 1 2 3 4 5 6 awk 'BEGIN { assoc["foo"] = "bar"; assoc["bar"] = "baz"; print("baz" in assoc); # => 0 print("foo" in assoc); # => 1 }'
带拆分的数组 1 2 3 4 5 awk 'BEGIN { split("foo:bar:baz", arr, ":"); for (key in arr) print arr[key]; }'
带有排序的数组 1 2 3 4 5 6 7 8 awk 'BEGIN { arr[0] = 3 arr[1] = 2 arr[2] = 4 n = asort(arr) for (i = 1; i <= n ; i++) print(arr[i]) }'
多维 1 2 3 4 5 6 awk 'BEGIN { multidim[0,0] = "foo"; multidim[0,1] = "bar"; multidim[1,0] = "baz"; multidim[1,1] = "boo"; }'
多维迭代 1 2 3 4 5 6 7 8 9 awk 'BEGIN { array[1,2]=3; array[2,3]=5; for (comb in array) { split(comb,sep,SUBSEP); print sep[1], sep[2], array[sep[1],sep[2]] } }'
Awk 条件 if-else 语句 1 2 3 4 5 6 awk -v count=2 'BEGIN { if (count == 1) print "Yes"; else print "Huh?"; }'
三元运算符 1 2 3 awk -v count=2 'BEGIN { print (count==1) ? "Yes" : "Huh?"; }'
存在 1 2 3 4 5 6 awk 'BEGIN { assoc["foo"] = "bar"; assoc["bar"] = "baz"; if ("foo" in assoc) print "Fooey!"; }'
不存在 1 2 3 4 5 6 awk 'BEGIN { assoc["foo"] = "bar"; assoc["bar"] = "baz"; if ("Huh" in assoc == 0 ) print "Huh!"; }'
switch 1 2 3 4 5 6 7 8 9 10 11 12 13 14 awk -F: '{ switch (NR * 2 + 1) { case 3: case "11": print NR - 1 break case /2[[:digit:]]+/: print NR default: print NR + 1 case -1: print NR * -1 } }' /etc/passwd
Awk 循环 for…i 1 2 3 4 awk 'BEGIN { for (i = 0; i < 10; i++) print "i=" i; }'
1 到 100 之间的 2 的幂 1 2 3 4 awk 'BEGIN { for (i = 1; i <= 100; i *= 2) print i }'
for…in 1 2 3 4 5 6 awk 'BEGIN { assoc["key1"] = "val1" assoc["key2"] = "val2" for (key in assoc) print assoc[key]; }'
Arguments 1 2 3 4 awk 'BEGIN { for (argnum in ARGV) print ARGV[argnum]; }' a b c
示例 反向记录 1 2 3 4 5 6 awk -F: '{ x[NR] = $0 } END { for (i = NR; i > 0; i--) print x[i] } ' /etc/passwd
反向字段 1 2 3 4 5 awk -F: '{ for (i = NF; i > 0; i--) printf("%s ",$i); print "" }' /etc/passwd
按记录求和 1 2 3 4 5 6 awk -F: '{ s=0; for (i = 1; i <= NF; i++) s += $i; print s }' /etc/passwd
总结整个文件 1 2 3 4 5 6 awk -F: ' {for (i = 1; i <= NF; i++) s += $i; }; END{print s} ' /etc/passwd
while 1 2 3 4 5 6 awk 'BEGIN { while (a < 10) { print "- " " concatenation: " a a++; } }'
do…while 1 2 3 4 5 6 7 awk '{ i = 1 do { print $0 i++ } while (i <= 5) }' /etc/passwd
Break 1 2 3 4 5 6 7 8 awk 'BEGIN { break_num = 5 for (i = 0; i < 10; i++) { print i if (i == break_num) break } }'
Continue 1 2 3 4 5 6 7 8 awk 'BEGIN { for (x = 0; x <= 10; x++) { if (x == 5 || x == 6) continue printf "%d ", x } print "" }'
Awk 格式化打印 用法 右对齐 1 2 awk 'BEGIN{printf "|%10s|\n", "hello"}' # | hello|
左对齐 1 2 awk 'BEGIN{printf "|%-10s|\n", "hello"}' # |hello |
通用说明符
特征符
描述
c
ASCII 字符
d
十进制整数
e
, E
, f
浮点格式
o
无符号八进制值
s
细绳
%
文字百分比
Space 空间 1 2 3 awk -F: '{ printf "%-10s %s\n", $1, $(NF-1) }' /etc/passwd | head -n 3
输出
1 2 3 root /root bin /bin daemon /sbin
1 2 3 4 5 awk -F: 'BEGIN { printf "%-10s %s\n", "User", "Home" printf "%-10s %s\n", "----","----"} { printf "%-10s %s\n", $1, $(NF-1) } ' /etc/passwd | head -n 5
输出
1 2 3 4 5 User Home ---- ---- root /root bin /bin daemon /sbin
各种各样的 正则表达式元字符
转义序列
:-
:-
\b
退格
\f
换页
\n
换行(换行)
\r
回车
\t
水平选项卡
\v
垂直选项卡
运行脚本 1 2 3 4 5 6 7 $ cat demo.awk# !/usr/bin/awk -f BEGIN { x = 23 } { x += 2 } END { print x } $ awk -f demo.awk /etc/passwd 69
另见