当前位置: 首页 > news >正文

7.Shell脚本修炼手册---awk基础入门版

awk 使用手册 - 常用版

文章目录

  • awk 使用手册 - 常用版
      • awk 介绍
      • awk 命令
        • awk 命令格式
        • awk 工作流
        • awk 使用示例
        • awk 命令选项
          • --help 选项
          • -F 选项:指定字段分隔符
          • -v 选项:预先定义变量
          • -p 选项:导出格式化的脚本代码
      • awk 内置变量 (常用)
        • 实例:内置变量的使用
      • awk 运算符 (常用)
        • 示例:运算符的使用
      • awk 输出重定向
        • 覆盖重定向 `>`
        • 追加重定向 `>>`
        • 管道 `|`
        • 双向管道 `|&`

awk 介绍

awk 是一个强大的文本分析工具,更像是一门轻量级编程语言。它支持自定义变量、条件语句、循环、数组、正则表达式和函数等功能,能灵活处理各种文本任务。

简单来说,awk 的工作逻辑是按行读取数据,根据设定的条件筛选行,再对筛选出的行执行操作。日常常用它来做这些事:

  • 处理文本(比如提取特定内容、替换字符)
  • 生成格式化的报告(比如统计结果按固定格式输出)
  • 执行简单的算术运算(比如求和、计数)
  • 处理字符串(比如计算长度、匹配子串)

awk 命令

awk 命令格式
awk [选项] '脚本' 文件名...  # 直接在命令行写处理逻辑(脚本)
awk [选项] -f 脚本文件 文件名...  # 从文件中读取处理逻辑(脚本)
  • 脚本:定义对数据的处理规则(比如筛选条件、输出内容)。
  • 文件名:awk 要处理的文件;也可以接收其他命令的输出作为输入(通过管道|)。
  • -f 脚本文件:如果处理逻辑复杂,可把脚本写在文件里,用-f指定文件路径。
awk 工作流

awk 处理数据的过程可以分为 3 步,按顺序执行:

  1. 执行BEGIN {命令}
    在读取任何输入数据之前执行,通常用来初始化变量、打印表头(比如统计报告的标题行)。
  2. 逐行处理模式 {命令}
    从输入中一行一行读数据,每读一行就检查是否符合 “模式”(比如包含某个关键词),符合就执行后面的 “命令”。
    如果省略 “模式”,默认对每一行执行 “命令”;如果 “命令” 是print,会默认打印整行。
  3. 执行END {命令}
    读完所有数据后执行,通常用来输出最终结果(比如统计的总和、计数)。
awk 使用示例

先准备一个示例文件employee.txt,包含员工编号、姓名、部门和年龄:

# 创建示例文件,内容如下
[bq@shell ~]$ cat << 'EOF' > employee.txt 
1)  张三  技术部  23
2)  李四  人力部  22
3)  王五  行政部  23
4)  赵六  技术部  24
5)  朱七  客服部  23
EOF

示例 1:打印所有雇员信息

# { print } 表示打印当前行(默认行为),等价于{ print $0 }($0代表整行)
[bq@shell ~]$ awk '{ print }' employee.txt 
1)  张三  技术部  23
2)  李四  人力部  22
3)  王五  行政部  23
4)  赵六  技术部  24
5)  朱七  客服部  23

示例 2:通过脚本文件打印雇员信息
如果处理逻辑较长,可把脚本写在文件中:

# 创建脚本文件commands.awk,内容为打印每一行
[bq@shell ~]$ cat commands.awk 
{ print }# 用-f指定脚本文件,效果和示例1相同
[bq@shell ~]$ awk -f commands.awk employee.txt 
1)  张三  技术部  23
2)  李四  人力部  22
3)  王五  行政部  23
4)  赵六  技术部  24
5)  朱七  客服部  23

示例 3:输出包含 “张三” 的行

# 模式为/张三/,表示匹配包含“张三”的行,匹配后执行{ print }(可省略)
[bq@shell ~]$ awk '/张三/ { print }' employee.txt 
1)  张三  技术部  23# 省略{ print },默认打印匹配的行
[bq@shell ~]$ awk '/张三/' employee.txt 
1)  张三  技术部  23

示例 4:统计部门包含 “术” 的员工数量
实验流程

  1. 定义匹配规则:筛选部门名称包含 “术” 的行(比如 “技术部”);
  2. 对匹配的行计数:每匹配一行,计数器count加 1;
  3. 所有行处理完后,在END块中打印计数结果。
[bq@shell ~]$ awk '
/术/ { count=count+1 }  # 匹配含“术”的行,count累加1(awk变量默认初始化为0)
END { print "Count="count }  # 所有行处理完后,打印总数
' employee.txt

运行结果:

Count=2  # 技术部有张三、赵六,共2人

示例 5:输出行总长度大于 10 的行
awk 的length(变量)函数可计算字符串长度,length($0)表示整行的长度:

# 模式为length($0)>10,即行长度大于10的行才打印
[bq@shell ~]$ awk 'length($0)>10 { print $0 }' employee.txt

所有行的长度都大于 18,因此输出所有行:

1)  张三  技术部  23
2)  李四  人力部  22
3)  王五  行政部  23
4)  赵六  技术部  24
5)  朱七  客服部  23
awk 命令选项
–help 选项

查看 awk 的帮助信息,包含所有选项和用法示例:

[bq@shell ~]$ awk --help
-F 选项:指定字段分隔符

默认用空格分隔一行中的字段(比如 “张三 技术部” 中,“张三” 是第 2 个字段,“技术部” 是第 3 个)。-F可自定义分隔符(比如冒号、逗号)。

示例:提取/etc/passwd中的用户名和家目录
/etc/passwd的内容格式为 “用户名:密码:UID:GID: 描述:家目录:shell”,用冒号分隔:

# 先查看第一行内容
[bq@shell ~]$ head -n1 /etc/passwd
root:x:0:0:root:/root:/bin/bash# 用-F:指定分隔符为冒号,打印第1个字段(用户名)和第6个字段(家目录)
[bq@shell ~]$ head -n1 /etc/passwd | awk -F : '{ print $1" "$6 }'
root /root  # 输出:用户名 家目录
-v 选项:预先定义变量

在 awk 处理数据前定义变量,可用于传递外部值(比如 Shell 变量)到 awk 中。

示例 1:传递 Shell 变量到 awk

# 在Shell中定义变量VAR=10000
[bq@shell ~]$ VAR=10000# 用-v VARIABLE=$VAR把VAR的值传给awk的VARIABLE变量,然后打印
[bq@shell ~]$ echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'
10000  # 输出传递的变量值

示例 2:直接在命令行定义变量
也可以在文件名前直接写 “变量 = 值”,传给 awk:

# Shell中定义var1和var2
[bq@shell ~]$ var1="aaa"
[bq@shell ~]$ var2="bbb"# 用v1=$var1 v2=$var2定义awk变量,打印这两个变量
[bq@shell ~]$ echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2
aaa bbb  # 输出变量值# 处理文件时同样有效
[bq@shell ~]$ awk '{ print v1,v2 }' v1=$var1 v2=$var2 /etc/hostname
aaa bbb  # 输出变量值(同时会打印/etc/hostname的内容,此处省略)
-p 选项:导出格式化的脚本代码

把 awk 脚本的执行逻辑(包括 BEGIN、处理过程、END)格式化后保存到文件,方便调试复杂脚本。

示例:导出脚本执行逻辑

# 执行一个包含BEGIN、处理行、END的脚本,用--profile导出逻辑到文件
[bq@shell ~]$ awk --profile '
BEGIN { printf"---|Header|--\n" }  # 开头打印表头
{ print }  # 打印每一行
END { printf"---|Footer|---\n" }  # 结尾打印表尾
' employee.txt > /dev/null  # 重定向输出到/dev/null,只保留导出文件

导出的文件默认名为awkprof.out,内容如下(包含执行次数和逻辑):

	# gawk profile, created Mon Apr  3 14:37:37 2023# BEGIN块(执行1次)BEGIN {1  	printf "---|Header|--\n"}# 处理行的逻辑(共5行数据,执行5次)5  {5  	print}# END块(执行1次)END {1  	printf "---|Footer|---\n"}

awk 内置变量 (常用)

awk 有很多内置变量,用于存储处理过程中的关键信息(比如当前行号、字段数)。用awk -d ''可导出所有内置变量到awkvars.out文件,以下是常用的几个:

变量描述例子(以employee.txt第一行为例)
$0表示当前行的完整内容$0 是 “1) 张三 技术部 23”
$n表示当前行的第 n 个字段(n 为数字)$2 是 “张三”,$3 是 “技术部”
FS字段分隔符(默认是空格)-F:指定后,FS 为 “:”
NF当前行的字段总数第一行有 4 个字段,NF=4
NR当前处理的行号(从 1 开始)处理第一行时 NR=1,第五行时 NR=5
FNR当前文件内的行号(多文件时有用)处理第一个文件的第一行时 FNR=1
OFS输出字段分隔符(默认是空格)设为 “,” 后,打印$2和$3 时用逗号分隔
ORS输出记录分隔符(默认是换行)设为 “;” 后,每行输出结尾用分号代替换行
实例:内置变量的使用

1. 用 NR 打印行号

# 打印行号+当前行内容(NR为行号,$0为整行)
[bq@shell ~]$ echo -e "一 二\n一 二 三\n一 二 三 四" | awk '{ print NR". "$0 }'
1. 一 二
2. 一 二 三
3. 一 二 三 四

2. 用 NF 筛选字段数大于 2 的行

# 只打印字段数>2的行(NF是当前行的字段总数)
[bq@shell ~]$ echo -e "一 二\n一 二 三\n一 二 三 四" | awk 'NF > 2'
一 二 三
一 二 三 四

3. 用 OFS 修改输出分隔符

# 把输出分隔符设为"|",打印$2和$3(默认用空格分隔,现在用|)
[bq@shell ~]$ awk 'BEGIN {OFS="|"} {print $2, $3}' employee.txt
张三|技术部
李四|人力部
王五|行政部
赵六|技术部
朱七|客服部

awk 运算符 (常用)

awk 支持多种运算符,和其他编程语言类似,常用的有:

类型运算符说明
赋值=、+=、-=、*=、/=例如 x+=2 等价于 x=x+2
算术+、-、*、/、%(取余)例如 5%2=1
自增 / 自减++、–x++(先使用 x 再 + 1)、++x(先 + 1 再使用 x)
关系<、<=、>、>=、==(等于)、!=(不等于)例如 x>10 判断 x 是否大于 10
正则匹配(匹配)、!(不匹配)$3 ~ / 技术 / 表示第 3 个字段包含 “技术”
逻辑&&(与)、||(或)、!(非)例如 x>0 && x<10 判断 x 是否在 0-10 之间
示例:运算符的使用

1. 赋值运算符

# 演示各种赋值运算(BEGIN块中直接执行,不处理输入)
[bq@shell ~]$ awk 'BEGIN { x=5; x+=2; print "x+=2后:"x }'  # x=5+2=7
x+=2后:7[bq@shell ~]$ awk 'BEGIN { x=5; x*=2; print "x*=2后:"x }'  # x=5*2=10
x*=2后:10

2. 逻辑运算符

# 逻辑与(&&):判断num是否在0-7之间
[bq@shell ~]$ awk '
BEGIN {num=5if (num>=0 && num<=7)  # 5>=0且5<=7,条件成立{ print "0<="num"<=7" }
}'
0<=5<=7  # 条件成立,输出结果
# 逻辑非(!):判断字符串是否为空
[bq@shell ~]$ awk '
BEGIN { site = ""  # 空字符串if (! length(site))  # length(site)=0,!0为真{ print "site是空字符串" }
}'
site是空字符串  # 条件成立,输出结果

3. 正则匹配运算符

# 匹配第3个字段(部门)包含“技术”的行
[bq@shell ~]$ awk '$3 ~ /技术/ { print $2"在"$3 }' employee.txt
张三在技术部
赵六在技术部

awk 输出重定向

awk 的输出(比如printprintf的结果)可以重定向到文件或通过管道传给其他命令,类似 Shell 的重定向。

覆盖重定向 >

把输出写入文件,覆盖文件原有内容(如果文件不存在则创建)。

# 先创建一个有内容的文件
[bq@shell ~]$ echo "旧内容:Hello World!" > /tmp/message.txt
[bq@shell ~]$ cat /tmp/message.txt
旧内容:Hello World!# 用>重定向,覆盖原有内容
[bq@shell ~]$ awk 'BEGIN { print "新内容:Hello awk!" > "/tmp/message.txt" }'
[bq@shell ~]$ cat /tmp/message.txt
新内容:Hello awk!  # 原有内容被覆盖
追加重定向 >>

把输出追加到文件末尾,保留原有内容

# 先创建一个有内容的文件
[bq@shell ~]$ echo "旧内容:Hello World!" > /tmp/message.txt
[bq@shell ~]$ cat /tmp/message.txt
旧内容:Hello World!# 用>>追加内容到末尾
[bq@shell ~]$ awk 'BEGIN { print "新内容:Hello awk!" >> "/tmp/message.txt" }'
[bq@shell ~]$ cat /tmp/message.txt
旧内容:Hello World!
新内容:Hello awk!  # 新内容追加在后面
管道 |

把 awk 的输出通过管道传给其他命令处理。

# 用tr命令把小写字母转为大写(awk的输出作为tr的输入)
[bq@shell ~]$ awk 'BEGIN { print "hello, world!" | "tr [a-z] [A-Z]" }'
HELLO, WORLD!  # tr处理后的结果
双向管道 |&

建立 awk 与外部命令的双向通信(既可发送数据给外部命令,也可接收外部命令的返回结果)。

示例:用 tr 转换大小写后,再读取结果

[bq@shell ~]$ awk 'BEGIN {cmd = "tr [a-z] [A-Z]"  # 定义外部命令:转大写print "hello, world!" |& cmd  # 发送数据给tr命令close(cmd, "to")  # 关闭向tr的输入cmd |& getline out  # 从tr接收处理结果,存到outprint out  # 打印结果close(cmd)  # 关闭双向管道
}'
HELLO, WORLD!  # 输出转换后的结果

如涉及版权问题,请联系作者处理!!!

http://www.dtcms.com/a/343491.html

相关文章:

  • camel中支持的模型与工具
  • 爬虫基础学习-POST方式、自定义User-Agent
  • FCN网络结构讲解与Pytorch逐行讲解实现
  • 小程序个人信息安全检测技术:从监管视角看加密与传输合规
  • 限流技术:从四大限流算法到Redisson令牌桶实践
  • SpringBoot整合HikariCP数据库连接池
  • 机器学习聚类算法
  • 【机器学习】线性回归
  • 深入解析C++非类型模板参数
  • Linux入门DAY29
  • AI 产业落地:从 “实验室神话” 到 “车间烟火气” 的跨越
  • 【TrOCR】模型预训练权重各个文件解读
  • SpringAI1.0.1实战教程:避坑指南25年8月最新版
  • 近端策略优化算法PPO的核心概念和PyTorch实现详解
  • Typescript入门-函数讲解
  • 创建一个springboot starter页面
  • LG P2617 Dynamic Rankings Solution
  • 1688 商品详情接口数据全解析(1688.item_get)
  • 关于从零开始写一个TEE OS
  • 如何安装 VMware Workstation 17.5.1?超简单步骤(附安装包下载)
  • Building Systems with the ChatGPT API 使用 ChatGPT API 搭建系统(第四章学习笔记及总结)
  • 一文讲清楚:场景、痛点、需求
  • mainMem.useNamedFile = “FALSE“ 的效果
  • UE5多人MOBA+GAS 52、下载源码构建引擎
  • 如何处理项目中棘手的依赖版本冲突问题
  • 软考中级【网络工程师】第6版教材 第3章 局域网 (下)
  • 构造参数注入解决循环依赖问题
  • 射频电路的完整性简略
  • rt-thread使用sfud挂载qspi flash的trace分析
  • Linux ELF二进制文件数字签名工具:原理与设计思路(C/C++代码实现)