文本处理之awk命令
awk是什么?
awk是linux里的一个文本处理的命令(工具),支持数学运算,流程该控制大量的变量和函数
awk命令的工作原理?
与sed命令一样,均是一行一行的读取、处理 sed作用于一整行的处理,而awk将一行分成数个字段来处理
awk 默认的分隔符是空白(空格、tab键)
-====================================
awk的数据字段变量
$0 表示整行文本
$1 表示文本中第一个数据字段
$2 表示文本中第二个数据字段
$n 表示文本中第n个数据字段
如/etc/passwd 文件以 " : " 作为分隔符,将数据格式分为7段,每段数据存入$1-$7变量中,$0存储的是整行的数据
awk命令的基本语法
awk -F 分隔符 ‘/模式/{动作}’ 输入文件 --》指令由模式和动作组合
awk的指令一定要用单引号括起
awk的动作一定要用花括号括起
模式可以是正则表达式、条件表达式或两种组合
如果模式是正则表达式就要用 / 定界符
多个动作之间用 ; 号分隔开
awk基本命令示例:
awk ‘/bash/’ /etc/passwd 只有模式没有动作结果和grep一样,显示$0
[root@localhost lxi]# awk ‘/bash/’ /etc/passwd
root❌0:0:root:/root:/bin/bash
longdd1❌1010:1010::/home/longdd1:/bin/bash
longdd2❌1011:1011::/home/longdd2:/bin/bash
longdd3❌1012:1012::/home/longdd3:/bin/bash
longdd4❌1013:1013::/home/longdd4:/bin/bash
who | awk ‘{print $2}’ 只有动作没有模式就直接执行动作
[root@localhost lxi]# who | awk ‘{print $2}’
tty1
pts/2
pts/3
awk -F: ‘/^h/{print $1,$7}’ /etc/passwd print 执行显示功能将文本输出到
[root@localhost lxi]# awk -F: ‘/^h/{print $1,$7}’ /etc/passwd
halt /sbin/halt
huangtao /bin/sh
haha /bin/bash
huangdaming /sbin/nologin
STDOUT(标准输出),以冒号作为分隔符,显示以h开头的行的第1列和第7列
[root@localhost lxi]# awk -F: ‘/[h]/{print $1,$7}’ /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
shutdown /sbin/shutdown
awk -F: ‘/[h]/{print $1,$7}’ /etc/passwd 不显示以h开头的行的第1列和第7列
[root@localhost lxi]# awk -F: ‘/[h]/{print $1,$7}’ /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
shutdown /sbin/shutdown
mail /sbin/nologin
awk -F ‘[: /]’ ‘{print $1,$10}’ /etc/passwd ==以 :或者 / 作为分隔符显示第1列和第10列 ==
[root@localhost lxi]# awk -F ‘[😕]’ ‘{print $1,$10}’ /etc/passwd
root bash
bin nologin
daemon nologin
adm sbin
lp
sync sync
shutdown shutdown
halt halt
mail
awk命令的完整语法
awk ‘BEGAN{commands}pattern{commands}END{commands}’ file1
1
BEGAN{} 表示处理数据前执行的命令
pattern{} 表示每行都执行的命令
END{} 表示处理数据后执行的命令
[root@localhost /]# cat /etc/passwd |awk -F: ‘BEGAN{print “######start######”} /bash$/{print $1,$7}END{print “######end######”}’
root /bin/bash
longdd1 /bin/bash
longdd2 /bin/bash
longdd3 /bin/bash
longdd4 /bin/bash
[root@localhost /]# cat /etc/passwd |awk -F: ‘BEGAN{num0;print “开始统计/etc/passwd文件”} $1~/feng/ || $3 > 1005 {print NR,NF,$1,length( 1 ) , 1), 1),(NF-1),$NF,$3;num++}END{print “统计结束”,num}’
awk的命令操作符
正则表达式和bash一致
数学运算:+,-,*,/,%,++,–
逻辑关系符:&&,||,!
比较操作符:>,<,>=,!=,<=,= =,!~
文本数据表达式:= =(精确匹配)
~ 波浪号表示匹配后面的模式(模糊匹配)
例1:who | awk ‘$2 ~ /pts/{print $1}’ 将第2个字段中包含pts的第1个字段列出
[root@localhost lxi]# who | awk ‘$2 ~ /pts/{print $1}’ root root
例2:awk -F: ‘$3 ~ /<…>/ {print $1,$3}’ /etc/passwd 将第3个字段只有3个字符的第1,3个字段列出
[root@localhost lxi]# awk -F: ‘$3 ~ /<…>/ {print $1,$3}’ /etc/passwd
systemd-coredump 999
systemd-resolve 193
polkitd 998
unbound 997
sssd 996
rngd 995
geoclue 994
nginx 993
sanle 520
chrony 519
pcp 518
例3:seq 100 |awk ‘$1 % 5 = = 0 || $1 ~ /^1/ {print $1}’ 将第1个字段能整除5或者以1开头的第1个字段列出来
[root@localhost lxi]# seq 100 |awk ‘$1 % 5 == 0 || $1 ~ /^1/ {print $1}’
1
5
10
11
12
例4:awk -F: ‘$1 = = “root” {print $1,$3}’ /etc/passwd 将第一个字段为root的字段1和字段3列出
[root@localhost lxi]# awk -F: ‘$1 == “root” {print $1,$3}’ /etc/passwd
root 0
例5:cat /etc/passwd | awk -F: '$1~/long/ {print $0}'将第1个字段包含long的所有字段列出
[root@localhost lxi]# cat /etc/passwd | awk -F: ‘$1~/long/ {print $0}’
longdd1❌1010:1010::/home/longdd1:/bin/bash
longdd2❌1011:1011::/home/longdd2:/bin/bash
longdd3❌1012:1012::/home/longdd3:/bin/bash
awk命令的内部变量
NF:每行$0的字段数
NR:当前处理的行号
FS:当前的输入分隔符,默认是空白字符(空格和tab)
OFS:当前的输出分隔符,默认是空格字符(空格)
例:1.awk -F: ‘{print NF}’ /etc/grub.conf 显示每行的字段数目
2.awk -F: ‘{print 1 , 1,1,NF}’ /etc/passwd 显示每行的第一个字段和最后一个字段
3.awk -F: ‘{print NR,$0}’ /etc/passwd 显示每行的内容和行号
4.awk -F: ‘BEGAN{OFS="—"}{print $1,$7}’ /etc/passwd 显示第1,7列,中间用—隔开
5.awk ‘BEGAN{FS=":"}/bash$/{print NR,$1}END{print NR}’ /etc/passwd 以 :作为分隔符,显示符合模式的用户名和所在的行号,最后显示总行号
ps:自定义的字符串和字段的拼接
[root@localhost shell_script]# who |awk ‘{print $2,“time is”,$4}’
tty1 time is 19:33
pts/0 time is 12:05
awk的if语句
单分支
if (condition) statement1
awk -F: ‘{if ($1 ~ /<…>/) print $0}’ /etc/passwd <====> awk -F: ‘
1
/
.
.
.
1~/^...
1 /.../ {print $0}’ /etc/passwd
awk -F: ‘{if ($3 >= 500) print $1,$7}’ /etc/passwd
if (condition) statement1 ; else statement2
awk -F: ‘{if ($3 != 0) print $1 ; else print $3}’ /etc/passwd
多分支
if (condition1) statement1 ; else if(condition2) statement2 ; else if(condition3) statement 3 ; else statement4
awk -F: ‘{if($1==“root”) print $1; else if($1==“ftp”) print $2; else if($1==“mail”) print $3; else print NR}’ /etc/passwd
练习:
如果/etc/passwd 文件的用户编号是0 ,则输出管理员;如果用户编号是1~999,输出程序用户;如果用户编号大于1000,输出普通用户,最后统计出有多少管理员、程序用户和普通用户。
[root@localhost ~]# cat /etc/passwd |awk -F: ‘BEGIN{a=b=c=0}{if($3==0)print “管理员”,a++;else if($3<1000&&$3>=1)print “程序用户”,b++;else print “普通用户”,c++}END{print “有"a"位管理员”,“有"b"位程序用户”,“有"c"位通用户”}’