Calcifer Calcifer 2 Calcifer 3 Calcifer 4
Linux

awk精确匹配和模糊匹配

2016/11/10 23:09 6666 次阅读 王梓
打赏
✸ ✸ ✸

awk 匹配的两种模式

awk 是 Linux 文本处理三剑客之一(grep、sed、awk)。在数据过滤场景中,经常需要区分"模糊匹配"和"精确匹配",两者的行为差异很大。

模糊匹配(正则匹配)

使用 //~ 运算符,只要行中包含匹配内容就命中:

$ cat data.txt
apple
application
pineapple
banana
app

# 模糊匹配:包含 "app" 的行全部命中
$ awk '/app/' data.txt
apple
application
pineapple
app

# 等价写法:$0 ~ /pattern/
$ awk '$0 ~ /app/' data.txt
apple
application
pineapple
app

这里 /app/ 是正则表达式,匹配行中任意位置出现的 "app"。

精确匹配(字符串相等)

使用 == 运算符,要求完全相等

# 精确匹配:只有完全等于 "app" 的行
$ awk '$0 == "app"' data.txt
app

# 对比:精确匹配 "apple"
$ awk '$0 == "apple"' data.txt
apple

匹配流程对比

输入行: "application"

模糊匹配 /app/:
  "application" 中包含 "app"? --> 是 --> 输出该行

精确匹配 == "app":
  "application" 完全等于 "app"? --> 否 --> 跳过

按字段匹配

实际工作中,数据通常是多列的,需要对特定字段做匹配:

$ cat users.txt
1001 zhangsan Beijing
1002 lisi Shanghai
1003 zhangwei Beijing
1004 wangwu Guangzhou

# 模糊匹配第2列包含 "zhang"
$ awk '$2 ~ /zhang/' users.txt
1001 zhangsan Beijing
1003 zhangwei Beijing

# 精确匹配第3列等于 "Beijing"
$ awk '$3 == "Beijing"' users.txt
1001 zhangsan Beijing
1003 zhangwei Beijing

# 精确匹配第2列等于 "lisi"
$ awk '$2 == "lisi"' users.txt
1002 lisi Shanghai

反向匹配(取反)

# 模糊匹配取反:不包含 "app" 的行
$ awk '!/app/' data.txt
banana

# 精确匹配取反:不等于 "app" 的行
$ awk '$0 != "app"' data.txt
apple
application
pineapple
banana

# 字段取反:第3列不是 "Beijing"
$ awk '$3 != "Beijing"' users.txt
1002 lisi Shanghai
1004 wangwu Guangzhou

正则匹配进阶

# 匹配以 "app" 开头的行
$ awk '/^app/' data.txt
apple
application
app

# 匹配以 "le" 结尾的行
$ awk '/le$/' data.txt
apple
pineapple

# 匹配数字
$ echo -e "abc\n123\na1b" | awk '/^[0-9]+$/'
123

# 匹配 IP 地址格式
$ awk '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/' access.log

实战场景

场景1:从日志中筛选特定状态码

# Nginx access.log 格式:IP - - [time] "request" status size
# 精确匹配状态码 500
awk '$9 == "500"' access.log

# 模糊匹配所有 5xx 错误
awk '$9 ~ /^5/' access.log

# 统计各状态码出现次数
awk '{print $9}' access.log | sort | uniq -c | sort -rn

场景2:从 /etc/passwd 筛选用户

# 精确匹配用户名
awk -F: '$1 == "root"' /etc/passwd

# 模糊匹配 shell 包含 "bash" 的用户
awk -F: '$7 ~ /bash/' /etc/passwd

# UID 大于 1000 的普通用户
awk -F: '$3 >= 1000' /etc/passwd

场景3:CSV 数据过滤

# 精确匹配部门为 "IT" 的员工
awk -F',' '$3 == "IT"' employees.csv

# 模糊匹配名字包含 "wang" 的员工(忽略大小写用 tolower)
awk -F',' 'tolower($2) ~ /wang/' employees.csv

匹配方式速查

需求语法说明
整行包含 pattern/pattern/模糊匹配
字段包含 pattern$N ~ /pattern/字段模糊匹配
整行等于 string$0 == "string"精确匹配
字段等于 string$N == "string"字段精确匹配
不包含 pattern!/pattern/模糊取反
字段不等于 string$N != "string"精确取反
以 pattern 开头/^pattern/正则锚定
以 pattern 结尾/pattern$/正则锚定

总结

记住一个核心区别:~// 是"包含"关系(模糊),== 是"等于"关系(精确)。日志分析、数据过滤时选对匹配方式,能避免很多误筛的坑。

✸ ✸ ✸

📜 版权声明

本文作者:王梓 | 原文链接:https://www.bthlt.com/note/6278277-Linuxawk精确匹配和模糊匹配

出处:葫芦的运维日志 | 转载请注明出处并保留原文链接

📜 留言板

留言提交后需管理员审核通过才会显示