简介

awk是处理文本文件的一个应用程序,几乎所有Linux系统都自带这个程序。它依次处理文件的每一行,以行为单位读取文本数据,然后以指定符号将这行数据分割成多个字符串单元,再对这些字符串单元进行操作。
awk的用法有很多,这里只记录一些常见的用法,方便日后遇到能够看懂,详细学习可查看菜鸟教程

详解

常用命令 awk -F ":" '{print $0}' /etc/passwd
以":"为分隔符分割 /etc/passwd 行单元,然后输出。
'{print $0}' "$0"是内置的变量,代表分割的所有字符串单元,"print"是内置的函数,具有输出功能,这里也可以写其他的函数,例如 printf ,是格式化输出函数。注意:这里一定要用单引号括住,否则会出错。命令执行效果:

awk -F ":" '{print $0}' /etc/passwd

root:x:0:0:root:/root:/usr/bin/zsh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin

cat /etc/passwd

root:x:0:0:root:/root:/usr/bin/zsh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin

cat /etc/passwd 的执行效果一样,这是因为 print $0 是输出所有的字符串单元格,可以查看一下变量:

$0完整的输入记录
$n当前记录的第n个字段

看一下 "$1" 的输出效果:

awk -F ":" '{print $1}' /etc/passwd

root
daemon
bin
sys
sync
games
man
lp
mail
news
uucp
proxy
www-data
backup
list
irc
gnats
nobody

很明显,只输出了每行的第一个 ":" 之前的字符串,可见 $1 是输出分割后第一个字符串单元,
显然 $2 是输出第二个,以此类推,超出则输出空字符串。

直接上实例,进一步讲解:

测试文件test.txt内容如下:
12 32 343 34123 421
Q23 QWE 123213Q 3412Q2
66W6QQ666QWWW

命令:awk -F "Q" '{print $1}' test.txt
12 32 343 34123 421

66W6
第二行输出空行,因为第二行"Q"在第一个字符,在"Q"前面相当于空字符串。
第一行全部输出,因为第二行没有"Q",相当于默认"Q"在这行行末。

命令:awk '{print $1}' test.txt
12
Q23
66W6QQ666QWWW
也可以不指定分隔符,默认分隔符为 空格或TAB 。

命令:awk -va=1 -vb=2 '{print $1+a,$1b}' test.txt
13 122
1 Q232
67 66W6QQ666QWWW2
可以通过"-v"声明变量使用,无须声明变量类型,会自动匹配。
第一行第一个输出"13",显然使用运算符加号"+",变量"a"是数字型变量,"$1"也会当成数字型变量。
第一行第二个输出"122",显示变量"a"和"$1"都是字符串型。
第二行第一个输出"1",显示变量"a"依旧是数字型,"$1"理应是"Q32",但是因为是加号运算符,所以会自动从头匹配所有数字型字符当数字型变量进行运算,但是"Q23"第一个字符是"Q",所以是"$1"变成 0 参与运算。
第三行第一个输出"67",与上同理。

看一下当声明的变量是非数字字符效果
命令:awk -va=2a -vb=b2 '{print $1+a,$1+b}' test.txt
14 12
2 0
68 66
由于运算符,变量"a、b和$1"都被转成数字型变量,所以"a==2;b==0",第一行"$1==12",第二行"$1==0",第三行"$1==66"。

awk支持的运算符:

= += -= = /= %= ^= *=赋值
?:C条件表达式
&&逻辑与
~ 和 !~匹配正则表达式和不匹配正则表达式
< <= > >= != ==关系运算符
空格连接
+ -加,减
* / %乘,除与求余
+ - !一元加,减和逻辑非
^ *求幂
++ --增加或减少,作为前缀或后缀
$字段引用
in数组成员
命令:awk '$1==12{print $1,$2,$3}' test.txt
12 32 343
仅输出了第一行三个字符串单元,这是因为加了过滤条件 "$1==12" ,只有第一行的"$1"等于12。

awk支持在 ’ ‘ 内加过滤条件,且过滤条件支持正则表达。

命令:awk '$0~/Q/{print $0}' test.txt
Q23 QWE 123213Q 3412Q2
66W6QQ666QWWW
  
可见输出了行内包含"Q"字符的整行。
/ /内写正则表达式,~ 代表匹配正则,!~ 代表不匹配正则。

命令:awk '$0!~/Q/{print $0}' test.txt
12 32 343 34123 421

awk中还存在一个东西----awk脚本。可以指定awk脚本来处理文本数据。
这里不详解,直接引用菜鸟教程的相关讲解内容。

关于 awk 脚本,我们需要注意两个关键词 BEGIN 和 END。
BEGIN{ 这里面放的是执行前的语句 }
END {这里面放的是处理完所有的行后要执行的语句 }
{这里面放的是处理每一行时要执行的语句}

假设有这么一个文件(学生成绩表):
命令:cat score.txt
Marry   2143 78 84 77
Jack    2321 66 78 45
Tom     2122 48 77 71
Mike    2537 87 97 95
Bob     2415 40 57 62

我们的 awk 脚本如下:
命令:cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
    math = 0
    english = 0
    computer = 0
 
    printf "NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL\n"
    printf "---------------------------------------------\n"
}
#运行中
{
    math+=$3
    english+=$4
    computer+=$5
    printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
    printf "---------------------------------------------\n"
    printf "  TOTAL:%10d %8d %8d \n", math, english, computer
    printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}

我们来看一下执行结果:
命令:awk -f cal.awk score.txt
NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL
---------------------------------------------
Marry  2143     78       84       77      239
Jack   2321     66       78       45      189
Tom    2122     48       77       71      196
Mike   2537     87       97       95      279
Bob    2415     40       57       62      159
---------------------------------------------
  TOTAL:       319      393      350
AVERAGE:     63.80    78.60    70.00

结语

awk的功能远远不止这些,这只是在基本的使用方法。在日后工作中或许会用到,至于高层次的用法,如果是shell开发,很有必要学习。