awk 是一个功能强大的编辑工具,逐行读取输入文本,默认以空格或tab键作为分隔符作为分隔,并按模式或者条件执行编辑命令。
以空格做为分隔符,多个空格他会自动压缩成一个
(1)按照命令找指定行
(2)对找到的行打印或其他操作,awk默认打印
(3)可以在无交互的情况下(不用进入真正的文件)实现相当复杂的文本操作,用于 Shell 脚本,完成各种自动化配置任务。
(1)先看BEGIN{action;… }这个模块是读取操作,读文件的所有行,所有读取完毕,然后一次执行
(2)END{action;… }打印,输出结果,对前面的结果条件判断,还可以用代码接着操作
对行分成多个字段进行处理(切片),执行结果可以通过print的功能将字段数据打印显示
awk ’'
awk 选项 ’模式或条件(操作)‘文件1 文件2…
“分隔符” 指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符
var=value 变量赋值
注:一定是单引号:‘模式或条件 {操作}’
{ }外指定条件,{ }内指定操作。
用逗号指定连续的行,用 || 指定不连续的行。&&表示”且“。
awk {print $1,$2,$3}
不能用双引号括起来,不然系统会把它当成字符串。
内置变量选项
选项 | 注释 |
---|---|
$0 | 当前处理的行的整行内容 打印所有 |
$n | 当前处理行的第n个字段(第n列) |
NR | 当前处理的行的行号(序数) |
NF | 当前处理的行的字段个数。$NF代表最后一个字段 |
FS | 列分割符。指定每行文本的字段分隔符,输入内容的分隔符,默认为空格或制表位。与"-F"作用相同 用-F可以不加单引号 -F:,用FS必须用=“” |
OFS | 输出内容的列分隔符 |
FILENAME | 被处理的文件名 |
RS | 行分隔符。awk从文件中读取资料时, 将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录进行处理。预设值是"\n" |
格式:awk ‘{print}’ 文件名
例:
awk '{print}' test.txt
11
22
33
44
(1)0和1放置{ }前,能够起到限制打印内容的作用(默认为"1"),如果为0,就不打印内容
格式:awk ‘0{print}’ test.txt
awk ‘1{print}’ test.txt
例:
[root@test1 ~]# awk '0{print}' test.txt
[root@test1 ~]# awk '1{print}' test.txt
11 qq 55
22 ww 55
33 ee 66
44 rr 77
(2)awk ‘{print $0}’ test1.txt ----$0,代表整行内容;awk是逐行读取处理,配合$0,就是打印所有内容
$1只取第一列,可以对行切片,输出列
awk '{print $1}' test.txt ——————————打印文件的第一列
11
22
33
44
(3)对/etc/passwd 取第一列和第四列
awk -F: '{print $1,$4}' /etc/passwd
root 0
bin 1
daemon 2
adm 4
lp 7
sync 0
shutdown 0
halt 0
awk '{print NR}' /etc/passwd #列出有多少行数
awk '{print NR,$0}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
格式:awk ‘NR==第几行{print}’ 文件名
例:
awk 'NR==3{print}' /etc/passwd——指定打印出第三行的内容
daemon:x:2:2:daemon:/sbin:/sbin/nologin
格式:awk ‘NR首打印行,NR末打印行{print}’ 文件名
例:
awk 'NR==3,NR==5{print}' /etc/passwd——打印3-5行的内容
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
可用正则表达式:
awk '(NR>=3)&&(NR<=5){print}' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
偶数行打印
awk 'NR%2==0{print NR,$0}' /etc/passwd
2 bin:x:1:1:bin:/bin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
8 halt:x:7:0:halt:/sbin:/sbin/halt
10 operator:x:11:0:operator:/root:/sbin/nologin
12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
奇数行打印
awk 'NR%2==1{print NR,$0}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
11 games:x:12:100:games:/usr/games:/sbin/nologin
13 nobody:x:99:99:Nobody:/:/sbin/nologin
[root@test1 ~]# awk 'BEGIN{print 20+30}'
50
[root@test1 ~]# awk 'BEGIN{print 20*30}'
600
[root@test1 ~]# awk 'BEGIN{print 20-30}'
-10
[root@test1 ~]# awk 'BEGIN{print 20/30}'
0.666667
[root@test1 ~]# awk 'BEGIN{print 10.23+12.11}'
22.34
[root@test1 ~]# awk 'BEGIN{print 10.23-12.11}'
-1.88
[root@test1 ~]# awk 'BEGIN{print 10.23*12.11}'
123.885
[root@test1 ~]# awk 'BEGIN{print 15/12.11}'
1.23865
[root@test1 ~]# awk 'BEGIN{print 2^3}'
8
[root@test1 ~]# awk 'BEGIN{print 2**3}'
8
当getline左右无重定向符号(“<”,“>”)或者管道符号(“|”)时,
awk首先读取的是第一行,而getline获取的是光标跳转至下一行的内容(也就是第二行)。
[root@test1 ~]# cat test.txt
11 qq 55
22 ww 55
33 ee 66
44 rr 77
[root@test1 ~]# awk '{getline;print $0}' test.txt
22 ww 55
44 rr 77
getline则作用定向输入文件,由于文件是刚打开,并没有被awk读入一行,
而只是getline读入,所以getline返回的是文件的第一行,而不是跳转至一行输入
原因:getline运行之后awk会改变NF,NR,$0,FNR等内部变量,所以此时读取$0的行号不再为1,而是2
[root@test1 ~]# awk '{getline < "test.txt";print $0 > "test1.txt";}' test.txt #将test的文件传送给test1文件中
[root@test1 ~]# ls
anaconda-ks.cfg ks.cfg test.txt 模板 图片 下载 桌面
initial-setup-ks.cfg test1.txt 公共 视频 文档 音乐
[root@test1 ~]# cat test1.txt
11 qq 55
22 ww 55
33 ee 66
44 rr 77
格式:awk ‘/^开头打印的字符/{print}’ 文件名
例:
awk '/^root/{print}' /etc/passwd————以root为开头打印
root:x:0:0:root:/root:/bin/bash
格式:awk ‘/结尾的打印字符$/{print}’ 文件名
例:
awk '/nologin$/{print}' /etc/passwd————以nologin结尾打印
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
格式:awk ‘BEGIN{…};{…};END{…}’ 文件
处理过程:
1、在awk处理指定的文本之前,需要先执行BEGIN{…}模式里的命令操作
2、中间的{…} 是真正用于处理文件的命令操作
3、在awk处理完文件后才会执行END{…}模式里的命令操作。END{ }语句块中,往往会放入打印结果等语句。
[root@test1 ~]# cat test.txt
11 qq 55
22 ww 55
33 ee 66
44 rr 77
[root@test1 ~]# awk 'BEGIN{x=1};{x++};END{print x}' test.txt
5
对字段进行处理打印:
[root@test1 ~]# head -n5 /etc/passwd |awk -F: '{print $1}'
root
bin
daemon
adm
lp
[root@test1 ~]# head -n5 /etc/passwd |awk -F: '{print $2}'
x
x
x
x
x
将/etc/passwd中的第一列和第二列的中间替换为+
[root@test1 ~]# fs=":";awk -v FS=$fs -v OFS="+" '{print $1,$3}' /etc/passwd
root+0
bin+1
daemon+2
adm+3
fs的是:然后使用-v给FS赋值=:,输入的时候FS是:,-v给OFS赋值输出的时候变量为+,然后打印第一列和第三列
将/etc/passwd中的第一列和第二列的中间替换为==
[root@test1 ~]# awk -v FS=':' -v OFS='==' '{print $1,$3}' /etc/passwd
root==0
bin==1
daemon==2
adm==3
lp==4
sync==5
#默认就是换行输出,不需要改
[root@test1 ~]# echo $PATH | awk -v RS=':' '{print $1}'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin
格式:awk -F: ‘第几列>大于的数值{print $0}’ /etc/passwd
例:
[root@test1 ~]# awk -F: '$3>500{print $0}' /etc/passwd
polkitd:x:999:997:User for polkitd:/:/sbin/nologin
libstoragemgmt:x:998:995:daemon account for
[root@test1 ~]# awk -F: '$3<=10{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
取反,uid小于10的行,所有列
[root@test1 ~]# awk -F: '!($3>10){print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
使用了if语句,内部条件(),外部条件{},整个加{}作为一条语句执行,相当于嵌套语法
[root@test1 ~]# awk -F: '{if ($3>500){print $0}}' /etc/passwd
polkitd:x:999:997:User for polkitd:/:/sbin/nologin
libstoragemgmt:x:998:995:daemon account for
格式:awk ‘(条件表达式)?(A表达式或者值):(B表达式或者值)’
[root@test1 ~]# awk -F: '{max=($3>=$4)?$3:$4;{print max,$0}}' /etc/passwd|sed -n '1,6p'————————比较passwd文件中以":"为分割的第三个和第四个字段的大小,
0 root:x:0:0:root:/root:/bin/bash
1 bin:x:1:1:bin:/bin:/sbin/nologin
2 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
7 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
5 sync:x:5:0:sync:/sbin:/bin/sync
max=($3>=$4)?$3:$4:这将变量 max 设置为输入行字段 3 和 4 之间的最大值。
? : 运算符是 if-else 语句的简写,因此此行等效于 if ($3 >= $4) { max=$3 } else { max=$4 }
取比较结果的最大值,赋值给变量max,并且输出max行的所有内容,然后打印其中的1-6行;
选项 | 注释 |
---|---|
$n(> < ==) | 用于对比数值 |
$n~“字符串” | 代表第n个字段包含某个字符串 |
$n!~“字符串” | 代表第n个字段不包含某个字符串 |
$n==“字符串” | 代表第n个字段为某个字符串 |
$n!=“字符串” | 代表第n个字段不为某个字符串 |
$NF | 代表最后一个字段 |
[root@test1 ~]# awk -F: '$7~"bash" {print $1,$NF}' /etc/passwd————输出第七个字段包含“bash”所在行的第一个字段和最后一个字段
root /bin/bash
zjf /bin/bash
输出第七个字段不包含“nologin”所在行的第一个字段和最后一个字段
[root@test1 ~]# awk -F: '$7!~"nologin" {print $1,$NF}' /etc/passwd
root /bin/bash
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
zjf /bin/bash
指定第六个字段为/home/zjf,第七个字段为/bin/bash,输出满足这些条件所在行的第一个和最后一个字段
[root@test1 ~]# awk -F: '($6=="/home/zjf")&&($7=="/bin/bash"){print $1,$NF}' /etc/passwd
zjf /bin/bash
指定第七个字段为/bin/bash 全部打印
awk -F: '$7=="/bin/bash" {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
zjf:x:1000:1000:zjf:/home/zjf:/bin/bash
代表第7字段不为/bin/bash的字符串全量打印
awk -F: '$7!="/bin/bash" {print $0}' /etc/passwd
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
[root@test1 ~]# awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[1]}'
20
[root@test1 ~]# awk 'BEGIN{a[0]=10 ; a[1]=20 ; a[2]=30;for(i in a)print i,a[i]}'
0 10
1 20
2 30
[root@test1 ~]# cat test2.txt
aaa
aaa
bbb
ccc
aaa
bbb
aaa
[root@test1 ~]# awk '{a[$1]++};END{for(i in a){print i,a[i]}}' test2.txt
aaa 4
ccc 1
bbb 2
[root@test1 ~]# awk '{print $1, $7, $9}' /var/log/messages
Jun software="rsyslogd" x-pid="706"
Jun Session of
Jun Session of
#在这个命令中,我们使用单引号将awk命令的操作包含起来。
$1、$7和$9是awk的内置变量,分别表示每行日志文件中的第1、第7和第9个字段。
通过使用print命令,我们将这些字段分别打印出来,以空格分隔。
最后,我们指定日志文件的路径/var/log/messages,awk会自动对文件中的每行进行处理并输出结果。
[root@test1 ~]# awk 'NR<=2{print $1, $4}' /var/log/messages
Jun test1
Jun test1