Awk 备忘清单

这是 GNU awk 的单页快速参考备忘单,其中涵盖了常用的 awk 表达式和命令。

入门

试试

该程序可用于选择文件中的特定记录并对其执行操作

  1. $ awk -F: '{print $1, $NF}' /etc/passwd

- - -
-F: 冒号作为分隔符
{...} awk 程序
print 打印当前记录
$1 第一个字段
$NF 最后一个字段
/etc/passwd 输入数据文件

Awk 程序

  1. BEGIN {<初始化>}
  2. <pattern 1> {<计划动作>}
  3. <pattern 2> {<计划动作>}
  4. ...
  5. END {< 最后的动作 >}

示例

  1. awk '
  2. BEGIN { print "\n>>>Start" }
  3. !/(login|shutdown)/ { print NR, $0 }
  4. END { print "<<<END\n" }
  5. ' /etc/passwd

变量

  1. $1 $2/$(NF-1) $3/$NF
  2. ┌──────┬──────────────┬───────┐
  3. $0/NR ID WEBSITE URI
  4. ├──────┼──────────────┼───────┤
  5. $0/NR 1 baidu.com awk
  6. ├──────┼──────────────┼───────┤
  7. $0/NR 2 google.com 25
  8. └──────┴──────────────┴───────┘

  1. # 第一个和最后一个字段
  2. awk -F: '{print $1,$NF}' /etc/passwd
  3. # 带行号
  4. awk -F: '{print NR, $0}' /etc/passwd
  5. # 倒数第二个字段
  6. awk -F: '{print $(NF-1)}' /etc/passwd
  7. # 自定义字符串
  8. awk -F: '{print $1 "=" $6}' /etc/passwd

查看: Awk 变量

Awk 程序示例

  1. awk 'BEGIN {print "hello world"}' # 打印 "hello world"
  2. awk -F: '{print $1}' /etc/passwd # -F: 指定字段分隔符
  3. # /pattern/ 仅对匹配的模式执行操作
  4. awk -F: '/root/ {print $1}' /etc/passwd
  5. # BEGIN 块在开始时执行一次
  6. awk -F: 'BEGIN { print "uid"} { print $1 }' /etc/passwd
  7. # END 块在最后执行一次
  8. awk -F: '{print $1} END { print "-done-"}' /etc/passwd

条件

  1. awk -F: '$3>30 {print $1}' /etc/passwd

查看: Conditions 条件

生成 1000 个空格

  1. awk 'BEGIN{
  2. while (a++ < 1000)
  3. s=s " ";
  4. print s
  5. }'

查看: Loops

数组 Arrays

  1. awk 'BEGIN {
  2. fruits["mango"] = "yellow";
  3. fruits["orange"] = "orange"
  4. for(fruit in fruits) {
  5. print fruit " 的颜色是 " fruits[fruit]
  6. }
  7. }'

查看: Awk 数组

函数 Functions

  1. # => 5
  2. awk 'BEGIN{print length("hello")}'
  3. # => HELLO
  4. awk 'BEGIN{print toupper("hello")}'
  5. # => hel
  6. awk 'BEGIN{print substr("hello", 1, 3)}'

查看: Functions

Awk 变量

内置变量

:- :-
$0 全线
$1, $2...$NF 第一个,第二个……最后一个字段
NR 记录总数(Number of Records)
NF N个字段(Nnumber of Fields)
OFS Output Field Separator
输出字段分隔符 (default “ “)
FS input Field Separator
输入字段分隔符 (default “ “)
ORS Output Record Separator
输出记录分隔符 (default “\n”)
RS input Record Separator
输入记录分隔符 (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. awk -F: '{sum += $3}
  2. END { print sum, sum/NR }
  3. ' /etc/passwd

打印参数

  1. awk 'BEGIN {
  2. for (i = 1; i < ARGC; i++)
  3. print ARGV[i] }' a b c

输出字段分隔符为逗号

  1. awk 'BEGIN { FS=":";OFS=","}
  2. {print $1,$2,$3,$4}' /etc/passwd

匹配位置

  1. awk 'BEGIN {
  2. if (match("One Two Three", "Tw"))
  3. print RSTART }'

匹配时长

  1. awk 'BEGIN {
  2. if (match("One Two Three", "re"))
  3. print RLENGTH }'

仅限 GNU awk

:- :-
ENVIRON 环境变量
IGNORECASE 忽略大小写
CONVFMT 转换格式
ERRNO 系统错误
FIELDWIDTHS 固定宽度字段

环境变量

:- :-
ARGC 数字或参数
ARGV 参数数组
FNR 文件记录数(File Number of Records)
OFMT 数字格式 (default “%.6g”)
RSTART 字符串中的位置
RLENGTH 比赛时长
SUBSEP 多维数组分隔符 (default “\034”)
ARGIND 参数索引

定义变量

  1. awk -v var1="Hello" -v var2="Wold" '
  2. END {print var1, var2}
  3. ' </dev/null

使用 shell 变量

  1. awk -v varName="$PWD" '
  2. 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. awk 'BEGIN {
  2. if ("foo" ~ "^fo+$")
  3. print "Fooey!";
  4. }'

不匹配

  1. awk 'BEGIN {
  2. if ("boo" !~ "^fo+$")
  3. print "Boo!";
  4. }'

如果在数组中

  1. awk 'BEGIN {
  2. assoc["foo"] = "bar";
  3. assoc["bar"] = "baz";
  4. if ("foo" in assoc)
  5. print "Fooey!";
  6. }'

Awk 函数

常用功能

函数 描述
index(s,t) 字符串 s 中出现字符串 t 的位置,如果未找到则为 0
length(s) 字符串 s 的长度(如果没有 arg,则为 $0)
rand 01 之间的随机数
substr(s,index,len) 返回从索引开始的 slen-char 子字符串(从 1 开始计数)
srand rand 设置种子并返回之前的种子
int(x) x 截断为整数值
split(s,a,fs) 将字符串 s 拆分为数组 afs 拆分,返回 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. awk '
  2. # 返回最小数量
  3. function find_min(num1, num2){
  4. if (num1 < num2)
  5. return num1
  6. return num2
  7. }
  8. # 返回最大数量
  9. function find_max(num1, num2){
  10. if (num1 > num2)
  11. return num1
  12. return num2
  13. }
  14. # 主功能
  15. function main(num1, num2){
  16. result = find_min(num1, num2)
  17. print "Minimum =", result
  18. result = find_max(num1, num2)
  19. print "Maximum =", result
  20. }
  21. # 脚本执行从这里开始
  22. BEGIN {
  23. main(10, 60)
  24. }
  25. '

Awk 数组

带索引的数组

  1. awk 'BEGIN {
  2. arr[0] = "foo";
  3. arr[1] = "bar";
  4. print(arr[0]); # => foo
  5. delete arr[0];
  6. print(arr[0]); # => ""
  7. }'

带键的数组

  1. awk 'BEGIN {
  2. assoc["foo"] = "bar";
  3. assoc["bar"] = "baz";
  4. print("baz" in assoc); # => 0
  5. print("foo" in assoc); # => 1
  6. }'

带拆分的数组

  1. awk 'BEGIN {
  2. split("foo:bar:baz", arr, ":");
  3. for (key in arr)
  4. print arr[key];
  5. }'

带有排序的数组

  1. awk 'BEGIN {
  2. arr[0] = 3
  3. arr[1] = 2
  4. arr[2] = 4
  5. n = asort(arr)
  6. for (i = 1; i <= n ; i++)
  7. print(arr[i])
  8. }'

多维

  1. awk 'BEGIN {
  2. multidim[0,0] = "foo";
  3. multidim[0,1] = "bar";
  4. multidim[1,0] = "baz";
  5. multidim[1,1] = "boo";
  6. }'

多维迭代

  1. awk 'BEGIN {
  2. array[1,2]=3;
  3. array[2,3]=5;
  4. for (comb in array) {
  5. split(comb,sep,SUBSEP);
  6. print sep[1], sep[2],
  7. array[sep[1],sep[2]]
  8. }
  9. }'

Awk 条件

if-else 语句

  1. awk -v count=2 'BEGIN {
  2. if (count == 1)
  3. print "Yes";
  4. else
  5. print "Huh?";
  6. }'

三元运算符

  1. awk -v count=2 'BEGIN {
  2. print (count==1) ? "Yes" : "Huh?";
  3. }'

存在

  1. awk 'BEGIN {
  2. assoc["foo"] = "bar";
  3. assoc["bar"] = "baz";
  4. if ("foo" in assoc)
  5. print "Fooey!";
  6. }'

不存在

  1. awk 'BEGIN {
  2. assoc["foo"] = "bar";
  3. assoc["bar"] = "baz";
  4. if ("Huh" in assoc == 0 )
  5. print "Huh!";
  6. }'

switch

  1. awk -F: '{
  2. switch (NR * 2 + 1) {
  3. case 3:
  4. case "11":
  5. print NR - 1
  6. break
  7. case /2[[:digit:]]+/:
  8. print NR
  9. default:
  10. print NR + 1
  11. case -1:
  12. print NR * -1
  13. }
  14. }' /etc/passwd

Awk 循环

for…i

  1. awk 'BEGIN {
  2. for (i = 0; i < 10; i++)
  3. print "i=" i;
  4. }'

1 到 100 之间的 2 的幂

  1. awk 'BEGIN {
  2. for (i = 1; i <= 100; i *= 2)
  3. print i
  4. }'

for…in

  1. awk 'BEGIN {
  2. assoc["key1"] = "val1"
  3. assoc["key2"] = "val2"
  4. for (key in assoc)
  5. print assoc[key];
  6. }'

Arguments

  1. awk 'BEGIN {
  2. for (argnum in ARGV)
  3. print ARGV[argnum];
  4. }' a b c

示例

反向记录

  1. awk -F: '{ x[NR] = $0 }
  2. END {
  3. for (i = NR; i > 0; i--)
  4. print x[i]
  5. }
  6. ' /etc/passwd

反向字段

  1. awk -F: '{
  2. for (i = NF; i > 0; i--)
  3. printf("%s ",$i);
  4. print ""
  5. }' /etc/passwd

按记录求和

  1. awk -F: '{
  2. s=0;
  3. for (i = 1; i <= NF; i++)
  4. s += $i;
  5. print s
  6. }' /etc/passwd

总结整个文件

  1. awk -F: '
  2. {for (i = 1; i <= NF; i++)
  3. s += $i;
  4. };
  5. END{print s}
  6. ' /etc/passwd

while

  1. awk 'BEGIN {
  2. while (a < 10) {
  3. print "- " " concatenation: " a
  4. a++;
  5. }
  6. }'

do…while

  1. awk '{
  2. i = 1
  3. do {
  4. print $0
  5. i++
  6. } while (i <= 5)
  7. }' /etc/passwd

Break

  1. awk 'BEGIN {
  2. break_num = 5
  3. for (i = 0; i < 10; i++) {
  4. print i
  5. if (i == break_num)
  6. break
  7. }
  8. }'

Continue

  1. awk 'BEGIN {
  2. for (x = 0; x <= 10; x++) {
  3. if (x == 5 || x == 6)
  4. continue
  5. printf "%d ", x
  6. }
  7. print ""
  8. }'

Awk 格式化打印

用法

右对齐

  1. awk 'BEGIN{printf "|%10s|\n", "hello"}'
  2. # | hello|

左对齐

  1. awk 'BEGIN{printf "|%-10s|\n", "hello"}'
  2. # |hello |

通用说明符

特征符 描述
c ASCII 字符
d 十进制整数
e, E, f 浮点格式
o 无符号八进制值
s 细绳
% 文字百分比

Space 空间

  1. awk -F: '{
  2. printf "%-10s %s\n", $1, $(NF-1)
  3. }' /etc/passwd | head -n 3

输出

  1. root /root
  2. bin /bin
  3. daemon /sbin

Header 标题头

  1. awk -F: 'BEGIN {
  2. printf "%-10s %s\n", "User", "Home"
  3. printf "%-10s %s\n", "----","----"}
  4. { printf "%-10s %s\n", $1, $(NF-1) }
  5. ' /etc/passwd | head -n 5

输出

  1. User Home
  2. ---- ----
  3. root /root
  4. bin /bin
  5. daemon /sbin

各种各样的

正则表达式元字符

  • \
  • ^
  • $
  • .
  • [
  • ]
  • |
  • (
  • )
  • *
  • +
  • ?

转义序列

:- :-
\b 退格
\f 换页
\n 换行(换行)
\r 回车
\t 水平选项卡
\v 垂直选项卡

运行脚本

  1. $ cat demo.awk
  2. #!/usr/bin/awk -f
  3. BEGIN { x = 23 }
  4. { x += 2 }
  5. END { print x }
  6. $ awk -f demo.awk /etc/passwd
  7. 69

另见