AWK使用笔记总结
1. AWK 简介
- AWK 是一种报告生成器和文本格式化工具,名字取自三位创始人(Alfred Aho, Peter Weinberger, Brian Kernighan)姓氏首字母。
- Linux 中使用的通常是 gawk(GNU awk)。
- 它本质上是一门编程语言,支持变量、数组、条件判断、循环等,可视为脚本解释器。
- 与 grep、sed 并称“Linux三剑客”:
- grep:擅长单纯的查找或匹配。
- sed:擅长编辑匹配到的文本。
- awk:擅长格式化文本,进行较复杂的处理。
2. 基本语法
awk [options] 'pattern { action }' file1 file2 ...
options:常用选项如-F(指定输入分隔符)、-v(设置变量)。pattern:匹配条件(可省略,省略即匹配所有行)。action:对匹配行执行的动作(如print、printf),必须用{}包围。
3. 动作(Action)
最常用的动作是 print 和 printf。
- 输出指定字段或整行。
- 内置变量:
$0:当前整行内容。$1, $2, ...:第1、第2…个字段。$NF:当前行的最后一个字段(NF表示字段总数)。$(NF-1):倒数第二个字段。
- 示例:
awk '{print $1, $3}' file # 打印第1和第3字段
awk '{print $0}' file # 原样输出整行
awk '{print "用户:", $1, "家目录:", $6}' /etc/passwd
printf
- 格式化输出,类似C语言,不会自动换行,需手动添加
\n。 - 常用格式符:
%s(字符串)、%d(整数)、%f(浮点数)、%-Ns(左对齐占N列)。 - 示例:
awk 'BEGIN{printf "%-10s %-15s\n", "用户", "家目录"} {printf "%-10s %-15s\n", $1, $6}' /etc/passwd
4. 模式(Pattern)
模式用于筛选行,满足条件的行才会执行动作。
4.1 空模式
- 不写任何条件,匹配所有行。
4.2 BEGIN / END 模式
BEGIN:在处理任何输入行之前执行,常用于输出表头。END:在所有输入行处理完后执行,常用于输出汇总信息。- 示例:
awk 'BEGIN{print "Start"} {print $0} END{print "End"}' file
4.3 关系运算模式
- 使用比较运算符:
<,<=,==,!=,>=,>。 - 示例:打印行号为偶数的行
awk 'NR % 2 == 0 {print $0}' /etc/passwd
4.4 正则模式
- 使用
/正则表达式/匹配行。 - 示例:匹配包含“root”的行
awk '/root/ {print $0}' /etc/passwd
- 支持
~(匹配)和!~(不匹配):
awk '$1 ~ /^[a-z]/' file # 第1字段以字母开头的行
4.5 行范围模式
- 格式:
/正则1/,/正则2/,表示从匹配正则1的行开始,到匹配正则2的行结束的所有行。 - 示例:打印从包含“start”到包含“end”之间的行
awk '/start/,/end/ {print}' file
5. 分隔符
5.1 输入分隔符(FS)
- 默认以空白字符(空格或Tab)为分隔符。
- 指定方式:
-F选项:awk -F: '{print $1}' /etc/passwd- 内置变量
FS:awk -v FS=':' '{print $1}' /etc/passwd
5.2 输出分隔符(OFS)
- 默认输出字段间以空格分隔。
- 通过
-v OFS=...修改。 - 示例:以逗号分隔输出
awk -v OFS=',' '{print $1, $2}' file
5.3 记录分隔符(RS / ORS)
RS(输入记录分隔符):默认换行符,可修改为其他字符,awk按此分割“行”。ORS(输出记录分隔符):默认换行符,输出时用指定符号代替换行。- 示例:以
$作为行分隔符
awk -v RS='$' '{print}' file
6. 常用内置变量
| 变量 | 含义 |
|---|---|
NF |
当前行的字段总数 |
NR |
当前行号(所有文件累计) |
FNR |
当前行号(每个文件单独计数) |
FILENAME |
当前处理的文件名 |
FS |
输入字段分隔符 |
OFS |
输出字段分隔符 |
RS |
输入记录分隔符 |
ORS |
输出记录分隔符 |
示例:
awk '{print NR, FNR, $0}' file1 file2 # 显示累计行号和文件内行号
7. 格式化输出(printf 占位符)
| 占位符 | 说明 |
|---|---|
%s |
字符串 |
%d / %i |
十进制整数 |
%f |
浮点数 |
%c |
ASCII字符 |
%x / %X |
十六进制(小写/大写) |
%% |
输出 % 本身 |
- 修饰符:
-左对齐,数字指定宽度,如%-20s。
8. 分支与循环
- 语法与C语言类似,但需写在
{}动作中。 - if-else:
awk '{ if ($3 > 1000) print $1, "高级用户"; else print $1, "普通用户" }' file
- for 循环:
awk '{ for (i=1; i<=NF; i++) print $i }' file
- while / do-while 同理,支持
break/continue。
9. 数组
- AWK 支持关联数组(索引可以是字符串)。
- 遍历数组:
for (key in array) { ... } - 示例:统计单词出现次数
awk '{ for (i=1; i<=NF; i++) count[$i]++ } END { for (w in count) print w, count[w] }' file
10. 常用函数
10.1 算术函数
rand():返回 0~1 随机数。srand():设置随机种子。int(x):取整。
10.2 字符串函数
length([str]):返回字符串长度(若不指定则返回当前行长度)。gsub(r, s [, t]):全局替换,在t中将所有匹配r的替换为s。split(str, arr [, sep]):将字符串按分隔符分割存入数组。- 示例:
awk '{ gsub(/old/, "new"); print }' file
awk '{ len = length($1); print len }' file
10.3 排序函数
asort(arr [, dest]):对数组值排序(会丢弃关联数组的键,变为数字索引)。- 若需保留键值并排序,可借助外部命令
sort:
awk '{ for (i in arr) print i, arr[i] }' file | sort -k2 -nr
11. 实际案例
案例1:统计各用户 shell 类型数量
awk -F: '{ shells[$NF]++ } END { for (s in shells) print s, shells[s] }' /etc/passwd
案例2:打印磁盘已用百分比(df 命令输出)
df -h | awk 'NR>1 {print $1, $5}' # 第5列是使用率
案例3:处理日志,统计访问IP次数
awk '{ ip[$1]++ } END { for (i in ip) print i, ip[i] }' access.log
12. 注意事项(避坑指南)
- 引号问题:awk 程序必须用英文单引号包围,内部变量(如
$1)不要加引号,但普通字符串需加双引号。 - 多行写法:单引号内可以换行,Bash会显示
>提示续行,最后闭合引号即可。 - 反斜杠换行:不要在单引号内使用
\换行,Bash 不会解释为续行,会导致语法错误。 - 正则中的斜杠:若正则包含
/,需转义(\/)。 {n,m}次数匹配:可能需要加上--posix或--re-interval选项。printf不换行:记得加\n。asort会丢弃关联键:若需保留键,使用外部sort或自己实现排序。
SED 使用总结笔记
1. SED 简介
- 全称:Stream Editor(流编辑器)。
- 工作方式:
sed逐行处理文本,将当前处理的行读入临时缓冲区(称为模式空间,Pattern Space),然后对缓冲区中的内容进行编辑处理,处理完成后将内容输出到屏幕。 - 重要特性:默认不修改源文件,除非使用
-i选项。所有操作都在内存中完成。
2. 基本语法
sed [选项] '脚本命令' 文件名
- 常用选项:
-n:静默模式。取消默认的输出(即不自动打印模式空间内容),常与p(打印)命令配合使用,只输出我们需要的行。-i:直接修改源文件(非常危险,建议使用前先备份或加后缀,如-i.bak)。-e:允许在同一行中执行多个脚本命令(逻辑分号;也可实现)。-f:从脚本文件中读取sed命令。
3. 核心命令详解
3.1 替换命令 s(最常用)
语法:[address]s/pattern/replacement/flags
- address:指定操作的行范围(详见第4节)。
- pattern:要匹配的旧内容(支持正则表达式)。
- replacement:替换后的新内容。
- flags(标记):
| 标记 | 作用 |
|---|---|
g |
全局替换。替换行内所有匹配到的内容(不加则只替换每行第一个)。 |
数字(如1,2) |
仅替换行内第N次匹配的内容。 |
p |
打印匹配到的行(通常与 -n 结合使用)。 |
w file |
将替换后的结果写入指定文件。 |
& |
代表匹配到的整个内容本身(用于引用匹配串)。 |
\n |
反向引用。匹配 \(\) 中分组的第n个内容。 |
\ |
转义特殊字符(如 /、&)。 |
实战示例:
# 基本替换(替换每行第一个 "lun")
sed 's/lun/LUN/' awk.txt
# 全局替换(替换所有 "lun")
sed 's/lun/LUN/g' awk.txt
# 只匹配含有"root" 的行,将这行中得bash替换为zsh
sed '/root/s/bash/zsh/' /etc/passwd
# 替换第2次出现的 "lun"
sed 's/lun/LUN/2' awk.txt
# 仅显示被修改的行(-n + p)
sed -n 's/lun/LUN/p' awk.txt
# 将替换结果写入新文件
sed -n 's/lun/LUN/w new.txt' awk.txt
# 使用 & 引用匹配内容(在匹配到的数字前后加括号)
echo "123" | sed 's/[0-9]*/(&)/' # 输出:(123)
# 反向引用 \1(交换单词位置)
echo "hello world" | sed 's/\([a-z]*\) \([a-z]*\)/\2 \1/' # 输出:world hello
# 替换路径时转义 "/"
sed -n 's/\/bin\/bash/\/bin\/sh/p' /etc/passwd
Tip:为了避免转义
/很繁琐,可以使用#或|作为分隔符,例如:sed 's#/bin/bash#/bin/sh#'
3.2 删除命令 d
删除匹配到的整行内容。
sed '3d' file # 删除第3行
sed '2,5d' file # 删除第2至第5行
sed '/root/d' file # 删除包含 "root" 的行
sed '/^$/d' file # 删除空行
sed '/start/,/end/d' # 删除从匹配 "start" 到 "end" 之间的所有行
3.3 追加与插入命令 a / i
a(append):在指定行的后面附加新文本。i(insert):在指定行的前面插入新文本。
sed '3a\新行内容' file # 在第3行后面添加一行
sed '/pattern/i\新行内容' file # 在匹配到的行前面插入
sed '1i\第一行' file # 在第一行之前插入
3.4 替换整行命令 c
将匹配到的一整行替换为指定的新文本(注意区分 s 只替换部分内容)。
sed '3c\这是新的一行' file # 将第3行整行替换
sed '/root/c\管理员账户' file # 将包含 root 的整行替换
3.5 打印命令 p
通常配合 -n 使用,只打印符合条件的行。
sed -n '3p' file # 只打印第3行
sed -n '/root/p' file # 只打印包含 root 的行
sed -n '2,5p' file # 只打印第2到第5行
3.6 写入与读取文件
w:将指定行写入到另一个文件(覆盖/新建)。r:将另一个文件的内容读取并插入到指定行之后。
# 将第3行写入 new.txt
sed '3w new.txt' file
# 将 read.txt 的内容插入到第5行后面
sed '5r read.txt' file
# 将文件内容插入到匹配 "end" 的行后面
sed '/end/r insert.txt' file
4. 地址范围(Address)详解
地址范围用于精确控制 sed 操作应用于哪些行。
| 写法 | 含义 |
|---|---|
空 |
应用于所有行。 |
3 |
仅第3行。 |
2,5 |
第2行到第5行。 |
1~2 |
从第1行开始,步进为2(即奇数行:1,3,5...)。 |
$ |
最后一行。 |
/pattern/ |
匹配正则表达式的行。 |
/start/,/end/ |
行范围模式。从匹配 start 的行开始,到匹配 end 的行结束(包含首尾)。 |
组合示例:
sed -n '1~2p' file # 打印奇数行
sed '$d' file # 删除最后一行
sed '/^#/d' file # 删除所有以 # 开头的注释行
sed '/^ftp/,/^mail/d' file # 删除以 ftp 开头到 mail 开头之间的行
5. 多命令执行
如果需要执行多个 sed 命令,可以使用 -e 选项或用分号 ; 分隔。
# 先用 -e 执行两个替换
sed -e 's/old1/new1/g' -e 's/old2/new2/g' file
# 等价于用分号(注意分号前要加反斜杠转义或放在引号内)
sed 's/old1/new1/g; s/old2/new2/g' file
6. 直接修改文件(-i 选项)
# 危险操作:直接修改原文件(无备份)
sed -i 's/old/new/g' file.txt
# 安全做法:修改前自动生成备份文件 file.txt.bak
sed -i.bak 's/old/new/g' file.txt
7. 实战案例集合
| 需求 | 命令 |
|---|---|
| 去除文件中的空行 | sed '/^$/d' file |
| 打印文件第5行 | sed -n '5p' file |
| 删除所有行首的空白符 | sed 's/^[ \t]*//' file |
在每一行行首添加 # |
sed 's/^/#/' file |
| 将文档中的 "dog" 全部替换为 "cat" | sed 's/dog/cat/g' file |
| 删除包含 "error" 的行及其后一行 | sed '/error/,+1d' file |
将配置文件中的 Port 80 改为 Port 8080 |
sed -i 's/Port 80/Port 8080/' /etc/service.conf |
8. 注意事项(避坑指南)
- 区分
s和c:s只替换行内的部分匹配内容;c是将整行换成全新的文本。 - 转义问题:替换内容中包含
/、&、\等特殊字符时,记得用\转义,或更换分隔符(如s#old#new#)。 -i慎用:线上生产环境建议先不加-i预览效果,确认无误后再加-i.bak备份修改。-n与p的组合:如果不加-n,sed会默认打印所有行,同时p又会重复打印匹配行,导致重复输出。查看特定行时,务必养成加-n的习惯。- 正则引擎:
sed默认使用基础正则表达式(BRE),部分元字符(如+、?、|、{n,m})需加反斜杠\才能生效。若想用扩展正则(ERE),可加-E选项(如sed -E 's/[0-9]+/NUM/g')。
grep 文本搜索过滤
作用:按模式匹配筛选行。
常用选项
| 选项 | 说明 |
|---|---|
-i |
忽略大小写 |
-v |
反向匹配(显示不包含模式的行) |
-c |
统计匹配行数(行数,非次数) |
-n |
显示匹配行行号 |
-o |
只显示匹配到的字符串(每个单独一行) |
-w |
匹配整个单词 |
-A n |
显示匹配行及其后 n 行 |
-B n |
显示匹配行及其前 n 行 |
-C n |
显示匹配行及其前后各 n 行 |
-e |
指定多个模式(逻辑 OR) |
-q |
静默模式,仅通过 $? 判断是否匹配 |
-E |
使用扩展正则(等同于 egrep) |
-P |
使用 Perl 兼容正则(支持 \d、\s 等) |
--color |
高亮匹配文本 |
基本语法
grep [选项] '正则模式' 文件
示例
# 忽略大小写查找 "error"
grep -i error /var/log/messages
# 统计包含 "root" 的行数
grep -c root /etc/passwd
# 显示匹配行及后2行
grep -A 2 'panic' /var/log/syslog
# 匹配整个单词 "bash"
grep -w bash /etc/passwd
# 多个模式(OR)
grep -e 'error' -e 'fail' log.txt
# 静默检查,用于脚本
if grep -q 'success' result.log; then
echo "成功"
fi
