awk用法
文本处理的命令;便于截取内容;支持小数运算
工作原理(与sed区分)
sed一样,均是一行行的读取、处理; sed是一整行处理,awk是将一行拆分成字段进行处理
完整语法
awk 'BEGIN{commands}pattern{commands}END{commands}'file BEGIN 执行数据前的命令
- pattern 每行都会执行的命令
- END 执行数据后的命令
例:以:为分隔符,查找passwd文件中以bash结尾,打出第一个字段和第七个字段
[root@localhost 1-28]# cat passwd | awk -F: 'BEGIN{print "--start--"} /bash$/{print $1,$7}END{print "--end--"} '
--start--
root /bin/bash
yalin /bin/bash
califeng /bin/bash
cali123 /bin/bash
zhaoliying /bin/bash
woshi1 /bin/bash
woshi2 /bin/bash
--end--
统计passwd文件行数
[root@localhost 1-28]# cat passwd | awk -F: 'BEGIN{i=0} {i++} END{print i}'
基本用法
- awk -F分隔符 ‘/模式/{动作}’ 文件;默认分割符是空白(空格或者tab键)
- awk的指令一定要用单引号括起来,动作一定要用花括号{}括起来
- 模式是正则表达式,要用/定界符
- 多个动作之间用;分隔
基本命令示例
只要模式没有动作结果和grep类似,显示$0
[root@localhost 1-28]# awk '/bash/' passwd
root:x:0:0:root:/root:/bin/bash
yalin:x:1009:1009::/home/yalin:/bin/bash
califeng:x:1010:1010::/home/califeng:/bin/bash
cali123:x:1011:1011::/home/cali123:/bin/bash
zhaoliying:x:1012:1012::/home/zhaoliying:/bin/bash
woshi1:x:1013:1013::/home/woshi1:/bin/bash
woshi2:x:1014:1014::/home/woshi2:/bin/bash
截取功能
[root@localhost 1-28]# who | awk '{print $2}'
tty1
pts/0
实现字符串拼接,自定义的字符串需要用""
[root@localhost 1-28]# who | awk '{print "time:"$4,$2}'
time:10:29 tty1
time:10:29 pts/0
~模糊匹配 ==精确匹配 !不匹配
[root@localhost 1-28]# who | awk '$2~"tt" {print $0}'
root tty1 2021-01-28 10:29
[root@localhost 1-28]# who | awk '$2=="tty1" {print $0}'
root tty1 2021-01-28 10:29
[root@localhost 1-28]# who | awk '$2!="tty1" {print $0}'
root pts/0 2021-01-28 10:29 (192.168.0.123)
与界定符号一同连用 \b不识别 只能使用<>
[root@localhost 1-28]# cat passwd | awk -F: '$1 ~ /\<....\>/ {print $1}'
root
sync
halt
mail
dbus
sssd
sshd
rngd
awk内置变量
- NR 代表当前处理的行号 number of record
- NF 代表一行的字段数量 number of field
- FS 当前输入分隔符,默认是空白(空格和tab)
- FNR 读取文件的记录数(行号),从1开始
- OFS 当前输出分隔符,默认是空格
例:输出who中第一个第二个以及最后一个字段,并且用-连接起来[root@localhost 1-28]# who | awk 'OFS="-"{print $1,$2,$NF}' root-tty1-10:29 root-pts/0-(192.168.0.123)
awk内置函数
- int(x)返回x的截断至整数的值
[root@localhost 1-9]# awk 'BEGIN {a=6.1572;result=int(a);print result}' 6
- rand()
返回任意数字n(0<=n<1)[root@localhost 1-9]# awk 'BEGIN {print rand()}' 0.924046 [root@localhost 1-9]# awk 'BEGIN {print rand()}' 0.924046 没有设置随机种子,则产生随机数相同
- srand()
常与rand()一同使用产生随机值
srand()需要写在BEGIN模块,才能正常产生随机数,这是awk的工作机制决定[root@localhost 1-9]# awk 'BEGIN {srand();print rand()}' 0.501409 [root@localhost 1-9]# awk 'BEGIN {srand();print rand()}' 0.0852438
- sub(旧字符串,新字符串,字符串)
第三个字符串是可选的,默认为$0[root@localhost 1-9]# awk 'BEGIN{ str="Hello World!";print "Before:" str;sub("World","Jack",str);print "After:" str }' Before:Hello World! After:Hello Jack!
- index(字符串1,字符串2)
在字符串1中查找字符串2,从1开始编号,得到字符串2的值;若没查找到则返回0[root@localhost 1-9]# awk 'BEGIN{ str="AA BB CC";subs="BB";ret=index(str,sub);printf ret}' 4
- ength(字符串)
返回字符串的长度[root@localhost 1-9]# awk 'BEGIN {str="hello!!I am Anna!";print length(str)}' 17
- split(字符串,数组,分隔符)
将字符串根据分隔符分割成一个个数组元素存入数组中[root@localhost 1-9]# awk 'BEGIN {str="AA,BB,CC,DD,EE";split(str,arr,",");for(i in arr){ print arr[i]}}' AA BB CC DD EE
- system
得到命令返回值;0表示上一条命令执行成功;非0表示上一条命令执行失败[root@localhost 1-9]# awk 'BEGIN { ret=system("date");print ret}' 2021年 01月 09日 星期六 20:48:17 CST 0
awk引用shell变量
- -v引用shell变量(当变量较少的时候)
[root@localhost 1-9]# name="lisi" [root@localhost 1-9]# echo | awk -v abc=$name '{print abc}' lisi
- 用双引号单引号以及$将变量括起来;
顺序是:双引号单引号$单引号双引号[root@localhost 1-9]# awk 'BEGIN{print "'$name'"}' lisi
- 使用双引号,awk内部的$0、$n等需要进行转义
[root@localhost 1-9]# abc=zhaoliying [root@localhost 1-9]# awk -F: "/^$abc/{print NR,\$0} " /etc/passwd 29 zhaoliying:x:1012:1012::/home/zhaoliying:/bin/bash [root@localhost 1-9]# awk -F: "/^$abc/{print \$1,\$3} " /etc/passwd zhaoliying 1012
- 使用单引号,拼接参数传参
sg=3 [root@localhost ~]# awk -F: '/root/{print $1,$'$sg'}' /etc/passwd root 0 operator 11 ------------------------------------------------------------------- [root@localhost ~]#awk -F: "/root/{print \$1,\$sg}" /etc/passwd root root:x:0:0:root:/root:/bin/bash operator operator:x:11:0:operator:/root:/sbin/nologin
练习
- 查看没有设置密码的用户(第二个字段为*或者!!则未设置)
cat shadow | awk -F: ‘BEGIN{i=0} {length($2)<=2;i++;print $1"没有设置密码"} END{print “有"i"个没有设置密码”}’ - 使用NF变量显示passwd文件倒数第二列的内容
cat passwd | awk -F’[: /]’ ‘{print $(NF-1)}’ - 显示passwd文件中第5到第10行的用户名
cat passwd | awk -F: ‘{print $1}’ | sed -n ‘5p;10p’
cat passwd | awk -F: ‘NR ~/<[5-9]|10>/ {print $1}’ - 显示passwd文件中行号是5结尾的行号和行
awk -F: ’ NR ~ /5$/ {print NR,$1}’ passwd - 用ip add只显示ip(不能使用tr或者cut命令)
ip add | awk ‘$NF ~/ens33/{print $2}’ | awk -F/ ‘{print $1}’ - 先使用ifconfig,使用awk显示eth0的入站流量和出站流量(字节)
ifconfig |head -8 | awk ‘$1 ~/RX/ && $4 ~ /bytes/ || $1 ~ /TX/ && $4 ~ /bytes/ {print $0}’
ifconfig | head -8 | awk ‘$0 ~ /RX.*bytes|TX.*bytes/ {print $5}’ - 使用awk命令统计以r开头的用户数目,显示如下效果
cat passwd | awk -F: ‘BEGIN{i=0} $1 ~ /^r/ {print $1;i++} END {print i};’ - 显示passwd文件中第7列不是bash的用户名
cat passwd | awk -F: ‘KaTeX parse error: Undefined control sequence: \< at position 7: 7 !~ /\̲<̲bash>/{print $1}’