简介
awk命令的名称来自其创始人 Alfred Aho、Peter Weinberger 和 Brian Kernighan 三个人姓氏的首字母。
awk命令实际上拥有自己的语言,即awk程序设计语言。三位创始人将语言命名为“样式扫描和处理语言”。awk允许创建简短的程序,用来读取输入文件,为数据排序,处理数据,对输入执行计算,生成报表等。
格式
awk命令的通用的语法格式为:
awk '{pattern + action}' {filenames}
其中pattern表示awk在数据中查找的内容。
action表示在找到匹配的内容后所需执行的一系列命令。
花括号{}用于根据特定的模式对一系列指令进行分组。
awk语言最基本的功能是在文件或者字符串中基于指定的规则浏览和抽取信息,根据抽取的信息执行相应的文本操作。
通常awk命令是以文件的“行”为处理单位。
实例
例如如下的实例:
[jamza@A23488809 master]$ awk '{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
sync:x:5:4:sync:/sbin:/bin/sync
shutdown:x:6:4:shutdown:/sbin:/sbin/shutdown
halt:x:7:4:halt:/sbin:/sbin/halt
operator:x:11:4:operator:/root:/sbin/nologin
#调用awk命令,指定 /etc/passwd 作为输入文件
#执行awk命令时,依次对/etc/passwd中的每一行执行{}中的print命令
#变量$0表示整行数据
再比如:
[jamza@A23488809 master]$ awk -F":" '{print $1}' /etc/passwd
root
bin
daemon
adm
sync
shutdown
halt
#调用awk命令,-F选项指定的每一行的字符分隔符为“:”
#变量$1表示按照分隔符,每一行分割的多列中的第一列,依次类推,$2、$3等分别表示第二列,第三列……
再比如:
[jamza@A23488809 master]$ awk -F":" '{ print $1 "^^^" $6 }' /etc/passwd
root^^^/root
bin^^^/bin
daemon^^^/sbin
adm^^^/var/adm
sync^^^/sbin
shutdown^^^/sbin
halt^^^/sbin
#print输出可以按照指定的格式输出数据
特殊的变量定义:
$0:表示整个当前行
$1:表示每行的第一个字段
$2:表示每行的第二个字段,依此类推
NF:表示每行的字段数量,比如/etc/passwd中的每行,按照:分割,有7个字段
NR:表示每行的记录号,即行号,从1开始,多文件记录递增
FNR:与NR类似,但是多文件记录不递增,每个文件都从1开始
\t:制表符
\n:换行符
FS:在BEGIN模块时定义的分隔符
RS:记录的分隔符,即每行的换行符。
BEGIN模块与END模块
通常对于每个输入行,awk都会执行每个脚本代码块一次,但是在许多编程情况下,可能需要在awk开始处理输入文件中的文本之前,执行初始化代码,因此awk允许定义一个BEGIN模块。
一般在BEGIN模块,会执行初始化字段分隔符(FS)变量,打印页眉,初始化全局变量等。
另外,在处理了输入文件中的所有行之后,会执行END模块,END模块用于执行最终计算。
比如,统计/etc/passwd中的账户人数:
[jamza@A23488809 master]$ awk '{count++;} END{print "user count is ",count}' /etc/passwd
user count is 27
[jamza@A23488809 master]$ awk 'BEGIN {count=0;print "[start] user count is ",count} {count=count+1} END{print "[end] user count is ",count}' /etc/passwd
[start] user count is 0
[end] user count is 27
比如,统计某个文件夹下的文件占用的字节数:
[jamza@A23488809 master]$ ll
总用量 1001060
drwxrwxr-x 5 jamza jamza 152 4月 11 13:56 base
-rw-rw-r-- 1 jamza jamza 130 3月 25 15:57 Dockerfile
-rw-rw-r-- 1 jamza jamza 1002212560 4月 11 13:56 docker_no_cntr_no_lpm_base.set
-rw-r--r-- 1 jamza jamza 13800882 3月 25 10:01 libarch_X86_64_lib_nsr.so
-rwxrwxr-x 1 jamza jamza 1958 4月 11 13:53 make_image_files.sh
drwxrwxr-x 3 jamza jamza 17 3月 25 10:01 opt
-rw-r--r-- 1 jamza jamza 9055464 3月 25 10:01 tipc.ko
-rwxrwxr-x 1 jamza jamza 927 4月 10 14:05 update_xml_offset.sh
[jamza@A23488809 master]$ ll | awk 'BEGIN{size=0;} {size=size+$5;} END{print "[end]size is ",size}'
[end]size is 1025072090
正则
在awk命令中的正则表达式,包含在符号//之间,如下:
^:行首定位符,如 /^root/ 表示匹配所有以root开头的行
$:行尾定位符,如 /root$/ 表示匹配所有以root结尾的行
.:匹配任意单个字符,如 /r…t/ 表示匹配字符r,加两个任意字符,再以t结尾
*:匹配0个或者多个前导字符,如 /a*ool/ 表示匹配0个或者多个a,再加ool,如ool、aaool、aaaaaool等
+:匹配1个或者多个前导字符,如 /a+b/ 表示匹配1个或者多个a,再加b,如ab、aab、aaaab等
?:匹配0个或者1个前导字符,如 /a?b/ 表示匹配b或者ab
[]:匹配指定字符组内的任意一个字符,如 /1/ 表示匹配以字符a或者b或者c开头的行
[^]:匹配不在指定字符组内任意一个字符,如 /[abc]/ 表示匹配不以字符a或者b或者c开头的行
():子表达式组合,如 /(root)+/ 表示一个或者多个rool组合,当一些字符需要组合时,使用()即可
|:或,如 /(root) | (jamza)/ 表示匹配root或者jamza的行
\:转义字符,如 /a/// 表示匹配a//
,!:分别表示匹配,不匹配的条件语句,如 $1~/root/ 表示第一个字段匹配正则表达式/root/的行
x{m}:x重复m次,如 /(root){3}/
x{m,}:x重复至少m次
x{m,n}:x重复至少m次,但不超过n次
正则表达式的应用格式:awk ‘/REG/{action}’ file。例如:
[jamza@A23488809 master]$ awk -F":" '$5~/root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
#表示字段5需匹配正则表达式/root/,即包含字符串root
布尔表达式的应用格式:awk ‘布尔表达式{action}’ file。例如
[jamza@A23488809 master]$ awk -F":" '$1=="root"{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[jamza@A23488809 master]$
[jamza@A23488809 master]$ awk -F":" '($1=="root")&&($5=="root") {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
abc ↩︎