AWK工具使用与技巧指南

发布于:2025-09-11 ⋅ 阅读:(17) ⋅ 点赞:(0)

#作者:张桐瑞

一、awk工具介绍

工作流程

  • 默认情况下,awk可以使用空白字符分割文本, awk内部可以分别$1, $2变量代表第一段内容 $0 :没有被分割的整行内容
  • -F选项指定分割符
  • 逐行处理

作用

  • 显示文本

二、awk基本使用

# awk [option] 'script' 文件名称  文件名称 

# awk [option] 'PATTERN{action}'  文件名称  文件名称

常用action:
print
printf 格式化输出(例:左对齐,右对齐)

1、print操作

[root@localhost ~]# sed -n '1p' /etc/passwd | awk -F: '{print $1}'
[root@localhost ~]# sed -n '1p' /etc/passwd | awk -F: '{print $0}'
[root@localhost ~]# sed -n '1p' /etc/passwd | awk -F: '{print $1, $3}'
[root@localhost ~]# sed -n '1,3p' /etc/passwd | awk -F: '{print "用户名:",$1}'
[root@localhost ~]# rpm -qa | grep php | awk -F-5 '{print "rpm -e --nodeps", $1}' | bash

卸载软件 rpm -e --nodeps

2、printf操作

格式化输出内容

  • 使用格式
    • printf “格式格式”,内容,内容
      • 占位符
        %s 字符串
        %d 整数
        %f 浮点数
[root@localhost ~]# awk '{printf "%s", $2}' /tmp/file01 
[root@localhost ~]# awk '{printf "%s%s", $2, $3}' /tmp/file01 

手动在引号里 加\n 换行

  1. 设置字符的宽度
  • %10s
[root@localhost ~]# awk '{printf "%20s", $2}' /tmp/file01 

默认数据在指定的宽度字符是以右对齐的方式显示

  1. 设置左对齐
  • %-10s
[root@localhost ~]# awk '{printf "%-20s", $2}' /tmp/file01 
  1. 默认没有换行,如果需要换行,手动添加换行符\n
[root@localhost ~]# awk '{printf "%-20s\n", $2}' /tmp/file01 

[root@localhost ~]# sed -n '1,3p' /etc/passwd | awk -F: '{printf "%-8s%-16s\n", $1, $7}'
[root@localhost ~]# df -hT | sed -n '/^\/dev/p' | awk '{printf "%-10s%-30s%-10s%-12s%-10s%-8s\n","磁盘名称:", $1, "挂载目录:", $7, "剩余空间:", $6}'

三、awk常用内置变量

1、FS

  • 相当于-F选项的作用
  • 保存行分割符,默认空白
[root@localhost ~]# sed -n '1p' /etc/passwd | awk -v FS=":" '{print $1}'

2、OFS

  • 指定awk显示多段内容时,多段内容间的分隔符
  • 默认空白字符
[root@localhost ~]# sed -n '1p' /etc/passwd | awk -v OFS="--->" -F: '{print $1, $7}'
root--->/bin/bash

3、NR

  • 记录行号
  • 处理多个文件时,所有文件的行号是连续记录的
[root@localhost ~]# awk '{print NR}' /etc/hosts /etc/redhat-release 

[root@localhost ~]# awk 'NR==3{print $0}' /etc/passwd

NR<=3 输出三行内容

4、FNR

  • 记录行号
  • 处理多个文件时,所有文件的行号是独立记录的
[root@localhost ~]# awk '{print FNR}' /etc/hosts /etc/redhat-release 

5、NF

  • 记录awk分割行后的段数
[root@localhost ~]# sed -n '1p' /etc/passwd | awk -F: '{print NF}'
[root@localhost ~]# awk '{print $NF}' /tmp/file01    //每一行分割的段数不同

{print NF} : 被分割的段数
$NF :就是被分割的最后一段

6、FILENAME

  • 保存awk正在处理的文件名
[root@localhost ~]# awk '{print FILENAME}' /tmp/file01 
/tmp/file01
/tmp/file01
/tmp/file01

[root@localhost ~]# awk '{print FILENAME}' /tmp/file01 | uniq
/tmp/file01

四、awk自定义变量

-v 变量名称=值 
[root@localhost ~]# awk -v name="martin" '{print "hello", name}' /etc/fstab 
[root@localhost ~]# awk -v number=100 '{print number}' /etc/fstab 

五、awk常用文本处理模式

1、表达式

  • 比较运算符
  1. ==, >, >=, <, <=, !=
  2. 数据 ~ 正则表达式
    • 判断数据是否可以被正则表达式
  3. 数据 !~ 正则表达式
  • 逻辑运算符
  1. && 并且
  2. || 或者
[root@localhost ~]# awk -F: '$3>=1 && $3 <= 999{print $1}' /etc/passwd
[root@localhost ~]# awk -F: '$7=="/sbin/nologin"{print $1}' /etc/passwd
[root@localhost ~]# awk -F: '$7 ~ "nologin$"{print $1}' /etc/passwd
[root@localhost ~]# df -hT | grep "^/dev" | awk '+$6>20{print "磁盘名称:", $1, "剩余空间", $5, "挂载目录:", $NF}'

+$6>20
转换成数字

2、/正则表达式/

[root@localhost ~]# netstat -antp | awk '/^tcp/{print $0}'
[root@localhost ~]# awk -F: '/^[rhg]/{print $1}' /etc/passwd
[root@localhost ~]# ls -l /etc/ | awk '/^-/{print $NF}'

3、/正则表达式/,/正则表达式/

[root@localhost ~]# awk '/Sep 26 09:02:30/,/Sep 26 09:18:04/{print $0}' /var/log/messages

4、BEGIN{}

  • 定义awk开始处理内容前执行的操作
[root@localhost ~]# sed -n '1,3p' /etc/passwd | awk -F: 'BEGIN{print "----数据开始----"}{print $1,$7}' 
[root@localhost ~]# awk 'BEGIN{name="martin"; print name}'

5、END{}

  • 定义awk处理内容后要执行的操作
[root@localhost ~]# sed -n '1,3p' /etc/passwd | awk -F: 'BEGIN{print "----数据开始-----"}{print $1, $7}END{print "----数据结束----"}'

[root@localhost ~]# awk -v number=0 '{number++}END{print number}' /etc/passwd

六、awk条件判断

1、语法

  • if (条件) {操作}
  • if (条件) {操作} else {操作}
  • if (条件) {操作} else if (条件) {操作}
[root@localhost ~]# awk -F: '{if($3==0) {print $1, "是管理员"} else {print $1, "是普通用户"}}' /etc/passwd
[root@localhost ~]# awk -F: -v bash_number=0 -v nologin_number=0 '{if($7=="/bin/bash") {bash_number++} else if($7=="/sbin/nologin") {nologin_number++}}END{print "bash用户数", bash_number, "nologin用户数", nologin_number}' /etc/passwd

七、awk循环

awk 本身就是按行循环,再来一个子循环就是循环每一行的每一段

1、for循环语法

for(变量定义; 循环条件; 改变变量的值) {操作}
for(i=1; i<=10; i++)
[root@localhost ~]# sed -n '1,3p' /etc/passwd | awk -F: '{for(i=1; i<=7; i++) {if(length($i)>=5) {print $i}}}'
[root@localhost ~]# awk '{for(i=1; i<=NF; i++) {if(length($i)>=4) {print $i}}}' /tmp/file01 

八、awk数组

1、定义数组

[root@localhost ~]# awk 'BEGIN{test[1]="martin"; test[2]="robin"; test[3]="lz"}'

[root@localhost ~]# awk 'BEGIN{test[1]="martin"; test[2]="robin"; test[3]="lz"; print test[2]}'
robin

2、获取数组中所有数据

[root@localhost ~]# awk 'BEGIN{test[1]="martin"; test[2]="robin"; test[3]="lz"; for(i=1; i<=3; i++) {print test[i]}}'

3、数组支持以任意数据作为下标

[root@localhost ~]# awk 'BEGIN{test["martin"]="北京"; test["robin"]="河北"; test["lz"]="天津"}'
[root@localhost ~]# awk 'BEGIN{test["martin"]="北京"; test["robin"]="河北"; test["lz"]="天津"; print test["robin"]}'
河北
[root@localhost ~]# awk 'BEGIN{test["martin"]="北京"; test["robin"]="河北"; test["lz"]="天津"; for(i in test) {print i}}'
robin
lz
martin
[root@localhost ~]# awk 'BEGIN{test["martin"]="北京"; test["robin"]="河北"; test["lz"]="天津"; for(i in test) {print test[i]}}'
河北
天津
北京
[root@localhost ~]# awk 'BEGIN{test["martin"]="北京"; test["robin"]="河北"; test["lz"]="天津"; for(i in test) {print "姓名:", i, "住址:", test[i]}}'
                                                                                    遍历数组data
[root@localhost ~]# awk -F: '{data[$7]++}END{for(i in data) {print i, data[i]}}' /etc/passwd
[root@localhost ~]# netstat -antp | awk '/^tcp/{tcp_number[$6]++}END{for(i in tcp_number) {print i, tcp_number[i]}}'

#  awk '{uv[$1]++}END{for(i in uv) {print i, uv[i]}}' access_log
#  awk '{pv[$7]++}END{for(i in pv) {print i, pv[i]}}' access_log

九、awk的内置函数

1、split(字符串,数组,行分割符)

使用分割符分割字符串, 将分割后的字符串保存到指定数组

#  awk 'BEGIN{split("a-b-c", data, "-"); print data[1]}'
#  awk 'BEGIN{split("a-b-c", data, "-"); print data[2]}'
#  awk 'BEGIN{split("a-b-c", data, "-"); print data[3]}

2、length(string)

返回string字符串的字符个数

#  awk 'BEGIN{print length("shell")}'

3、substr(string,start [,length])

取string字符串中的子串,从start开始,取length个;start从1开始计数

#  awk 'BEGIN{data=substr("hello",2, 3); print data}'

4、system(command)

支持在awk内部调用shell命令

 #  awk 'BEGIN{system("ifconfig enp2s0")}'

5、systime()

返回系统当前时间

#  awk 'BEGIN{print systime()}'
#  awk 'BEGIN{now=systime(); print strftime("%F_%T", now)}'

6、tolower(string)

将string中的所有字母转为小写

#  awk 'BEGIN{print tolower("aBcD")}'

7、toupper(string)

将string中所有字母转换为大写

#  awk 'BEGIN{print toupper("aBcD")}'

网站公告

今日签到

点亮在社区的每一天
去签到