Shell—12.awk
awk是一门语言,类似于C语言。awk一般用于统计,过滤,计算。awk按行处理文件
基本语法
- awk options pattern{action} file
| awk 可选参数 模式/条件 动作 文件/数据
- awk '条件1{动作1} 条件2{动作2}...' 文件名
- action
| awk擅长文本格式化,且输出格式化后的结果。最常见print和printf
| 除了使用格式流输出,还有用流程控制语句作为action
- pattern
| 一般使用关系表达式作为pattern
- awk 必须外层使用单引号,内层使用双引号
| 内置变量不要加双引号,否则会被识别为文本,尽量不加引号
- options
| -F 指定分割字段符
| -v 定义或修改awk内部的变量
| -f 从脚本文件中读取awk命令
- awk有一些内置变量
| NR 表示行号
| NF 表示列号 倒数就是 NF-X
- 一个等于号是修改变量值,两个等于号是关系运算符。
- awk分割符有两种
| 输入分隔符,awk默认空格,英文field separator,变量名FS
| 输出分隔符,output field separator,简称OFS
--- 提取ip地址示例 ---
[root@wg ~]# ifconfig | awk 'NR==2'
inet 192.168.3.111 netmask 255.. broadcast 192..
[root@wg ~]# ifconfig | awk 'NR==2{print NF,$0}'
6 inet 192.168.3.111 netmask 255.. broadcast 192..
# 默认直接输出,无分割。加逗号才能在两个变量间输出空格
[root@wg ~]# ifconfig | awk 'NR==2{print $2}'
192.168.3.111
--- 提取用户名示例 ---
[root@wg ~]# awk "NR==5" /etc/passwd
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@wg ~]# awk 'NR==1,NR==3{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
[root@wg ~]# awk -F ":" 'NR==1,NR==3{print $1}' /etc/passwd
root
bin
daemon
[root@wg ~]# awk -v FS=":" 'NR==1,NR==3{print $1}' /etc/passwd
root
bin
daemon
[root@wg ~]# awk -v FS=":" 'NR==1,NR==3{print $1"|"$(NF-0)}' /etc/passwd
root|/bin/bash
bin|/sbin/nologin
daemon|/sbin/nologin
# NF的值是列数,$调取出来当然是最后一列
[root@wg ~]# awk -F ":" -v OFS="|" 'NR==1,NR==3{print $1,$6}' /etc/passwd
root|/root
bin|/bin
daemon|/sbin
内置变量
- FS 输入字段分隔符,默认为空
- OFS 输出字段分隔符,默认为空
- RS 输入记录分隔符(输入换行符),指定输入时的换行符
- ORS 输出记录分隔符(输出换行符),输出时用指定符号代替换行符
- FNR 各文件分别计数的行号
- FILENAME 当前文件名
- ARGC 命令行参数的个数
- ARGV 数组、保存的是命令行所给定的各参数
[root@wg ~]# awk -F ":" 'NR==1,NR==3{print $1}' /etc/passwd
root
bin
daemon
[root@wg ~]# awk -v RS=":" 'NR==1,NR==3{print $1}' /etc/passwd
root
x
0
[root@wg ~]# awk -F ":" -v ORS="##" 'NR==1,NR==3{print $1}' /etc/passwd
root##bin##daemon##
[root@wg ~]# awk -F ":" 'NR==1,NR==3{print FILENAME,$1}' /etc/passwd
/etc/passwd root
/etc/passwd bin
/etc/passwd daemon
[root@wg ~]# awk -F ":" 'NR==1,NR==3{print ARGV[0],$1}' /etc/passwd
awk root
awk bin
awk daemon
- ARGV是一个数组,里边默认是 awk 文件名
- 传入1的话,就是文件名
[root@wg ~]# awk -v myname="wg" 'BEGIN{print "我的名字是:",myname}'
我的名字是:wg
[root@wg ~]# myname="wg"
[root@wg ~]# awk -v myname=$myname 'BEGIN{print "我的名字是:",myname}'
我的名字是:wg
操作示例
df -h | grep /home | awk '{print $5}' |cut -d "%" -f 1
- BEGIN
| awk 'BEGIN{print "test!!"}' {print $2 "\t" $5} student.txt
- FS位置变量 作用是指定分割符
| awk '{FS=":"}{print $1 "\t" $3}' /etc/passwd
| awk 'BEGIN{FS=":"}{print $1 "\t" $3}' /etc/passwd
- END
| awk 'END{printf "The End\n"}{printf $2 "\t" $3 "\n"}' student.txt
- FS
| cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf $1 "\t" $3 "\n"}'
- 支持关系运算符
| cat student.txt | grep -v Name | awk '$6>=87 {printf $2 "\n"}'
模式
[root@wg ~]# awk -F ":" 'BEGIN{print "begin"}NR==1{print $1}' /etc/passwd
begin
root
[root@wg ~]# awk -F ":" 'END{print "begin"}NR==1{print $1}' /etc/passwd
root
begin
操作示例
[root@wg ~]# echo 1:2:3:4|awk 'BEGIN{FS=":";OFS="-"}{NF+=0}1'
1-2-3-4
[root@wg ~]# echo 1:2:3:4|awk 'BEGIN{FS=":";OFS="-"}NF+=0'
1-2-3-4
[root@wg ~]# echo 1:2:3:4|awk 'BEGIN{FS=":";OFS="-"}{NF+=0}{print $0}'
1-2-3-4
[root@wg ~]# echo 1:2:3:4|awk 'BEGIN{FS=":";OFS="-"}NF+=0{print $0}'
1-2-3-4
- BEGIN{} 特殊的pattern,最常用于变量赋值。
- BEGIN 这个pattern就是文件没开始读的时候执行
- 'BEGIN{FS=":";OFS="-"}{NF+=0}1' 对应处理是 1:2:3 --> 1-2-3
- awk有个问题,没有对字段进行操作,它是不会改变输出分隔符的,
- NF+=0,这个赋值没用,NF值也没变。仅对字段进行了操作,会使OFS生效。
# 总结: 设置OFS,必须进行个字段操作。
# 感觉很生涩,远远不如Python好用
--- 半年没写了,凭记忆写一个python ---
print("1:2:3:4".replace(":","-")) // 忘了加不加逗号了
1-2-3-4
print和printf
- 1.printf需要指定format;print不用指定
| format用于指定后面的每个item的输出格式
- 2.printf不自动打印换行符: \n ;print默认添加空格换行符
- format格式的提示符都以%开头,后缀一个字符
| %c 显示字符的ascii码
| %d,%i 十进制整数
| %e,%E 科学计数法显示数值
| %f 显示浮点数
| %g,%G 以科学计数法的格式或浮点数的格式显示数值
| %s 显示字符串
| %w 无符号整数
| %% 百分号本身
- printf修饰符
| - 左对齐 默认是右对齐
| + 显示数值正负符号 printf "%+d"
[root@wg ~]# awk 'NR==1,NR==3{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
[root@wg ~]# awk 'NR==1,NR==3{printf "%s\n",$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
[root@wg ~]# printf "%d\n%d\n%d\n%d\n" 1 2 3 4
1
2
3
4
关系运算符
- 支持关系运算符
- 前边的NR==1,NR==3 直接 NR<4
正则的使用
- awk '/正则表达式/动作' 文件
- 正则可以看做是条件了,还可以加普通条件
awk "\$2 ~ /$md$/"
awk '$2 ~ /'$md'$/'
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律