CentOS Stream 9入门学习教程,从入门到精通,CentOS Stream 9 的过滤器 —— 语法详解与实战案例(18)

CentOS Stream 9 的过滤器 ------ 语法详解与实战案例

系统环境:CentOS Stream 9 / RHEL 9

核心工具:grep, sed, awk, cut, wc, sort, uniq, Perl

目标:掌握 Linux 文本处理全流程,从基础过滤到高级编程


一、简单过滤器(基础文本处理工具)


1.1 cat ------ 连接并显示文件内容

✅ 语法:

bash 复制代码
cat [选项] [文件...]

✅ 常用选项:

选项 说明
-n 显示行号
-b 显示非空行的行号
-s 压缩连续空行
-A 显示所有字符(包括不可见字符)

✅ 示例:

bash 复制代码
# 创建测试文件
echo -e "Line 1\n\nLine 3\n  \nLine 5" > test.txt

# 显示内容(默认)
cat test.txt

# 显示行号(包括空行)
cat -n test.txt
# 输出:
#      1	Line 1
#      2	
#      3	Line 3
#      4	  
#      5	Line 5

# 压缩空行并显示非空行号
cat -sb test.txt
# 输出:
#      1	Line 1
#      2	Line 3
#      3	Line 5

1.2 head / tail ------ 查看文件开头/结尾

✅ 语法:

bash 复制代码
head -n N file    # 显示前N行
tail -n N file    # 显示后N行
tail -f file      # 实时追踪文件末尾(日志监控)

✅ 示例:

bash 复制代码
# 显示前3行
head -n 3 /etc/passwd

# 显示后5行
tail -n 5 /var/log/messages

# 实时监控日志(按 Ctrl+C 退出)
tail -f /var/log/secure

1.3 nl ------ 添加行号(比 cat -n 更灵活)

✅ 语法:

bash 复制代码
nl [选项] [文件]

✅ 常用选项:

选项 说明
-b a 所有行编号(包括空行)
-b t 只对文本行编号(默认)
-n ln 行号左对齐
-w N 行号宽度为N

✅ 示例:

bash 复制代码
nl -b a -n ln -w 3 test.txt
# 输出:
# 1     Line 1
# 2     
# 3     Line 3
# 4       
# 5     Line 5

1.4 tac ------ 反向显示文件(从最后一行开始)

✅ 语法:

bash 复制代码
tac [文件]

✅ 示例:

bash 复制代码
echo -e "A\nB\nC" > abc.txt
tac abc.txt
# 输出:
# C
# B
# A

1.5 rev ------ 反转每行字符

✅ 语法:

bash 复制代码
rev [文件]

✅ 示例:

bash 复制代码
echo "Hello World" | rev
# 输出:dlroW olleH

# 反转 /etc/passwd 每行(用于密码逆向分析?慎用)
rev /etc/passwd | head -n 3

1.6 wc ------ 统计行数、字数、字符数

✅ 语法:

bash 复制代码
wc [选项] [文件]

✅ 常用选项:

选项 说明
-l 行数
-w 单词数
-c 字节数
-m 字符数(支持UTF-8)

✅ 示例:

bash 复制代码
wc -l /etc/passwd        # 统计行数
wc -w /etc/group         # 统计单词数
wc -c /etc/hosts         # 统计字节数
wc -m /etc/issue         # 统计字符数(含中文)

# 统计多个文件
wc -l *.log

1.7 sort ------ 排序

✅ 语法:

bash 复制代码
sort [选项] [文件]

✅ 常用选项:

选项 说明
-n 按数值排序
-r 逆序
-k N 按第N列排序
-t C 指定分隔符为C
-u 去重(需先排序)

✅ 示例:

bash 复制代码
# 按字母排序
echo -e "banana\napple\ncherry" | sort
# 输出:apple, banana, cherry

# 按数值排序
echo -e "10\n2\n100" | sort -n
# 输出:2, 10, 100

# 按第二列排序(: 分隔)
sort -t: -k3n /etc/passwd | head -n 5

1.8 uniq ------ 去除相邻重复行(必须先排序!)

✅ 语法:

bash 复制代码
uniq [选项] [文件]

✅ 常用选项:

选项 说明
-c 统计重复次数
-d 只显示重复行
-u 只显示唯一行

✅ 示例:

bash 复制代码
echo -e "A\nA\nB\nC\nC\nC" | uniq -c
# 输出:
#       2 A
#       1 B
#       3 C

# 统计登录失败IP(需先排序)
grep "Failed password" /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -nr

二、正则表达式(Regular Expressions)

正则表达式是文本处理的核心,广泛用于 grep/sed/awk/Perl 等工具。


2.1 基本元字符

元字符 说明 示例
. 任意单字符 a.c → abc, aXc
^ 行首 ^root → 以 root 开头的行
$ 行尾 bash$ → 以 bash 结尾的行
* 前字符0次或多次 a* → "", "a", "aaa"
[abc] 字符集合 [aeiou] → 匹配任意元音字母
[^abc] 非字符集合 [^0-9] → 非数字

✅ 示例:

bash 复制代码
# 匹配以 # 开头的行(注释)
grep "^#" /etc/ssh/sshd_config

# 匹配以 .conf 结尾的行
grep "\.conf$" /etc/rsyslog.conf

2.2 特殊字符元字符(需转义)

元字符 说明 示例
\d 数字 [0-9] \d{3} → 三位数字
\w 字母数字下划线 \w+ → 单词
\s 空白字符 \s+ → 一个或多个空格/tab
\b 单词边界 \broot\b → 匹配单词 root,不匹配 groot

✅ 注意:在基础 grep 中需使用 \d 等需 -P 参数(Perl 正则)或改用 [0-9]


2.3 POSIX 字符类(兼容性好)

说明 等价
[:digit:] 数字 [0-9]
[:alpha:] 字母 [a-zA-Z]
[:alnum:] 字母+数字 [a-zA-Z0-9]
[:space:] 空白字符 [ \t\n\r\f\v]
[:upper:] 大写字母 [A-Z]
[:lower:] 小写字母 [a-z]

✅ 示例:

bash 复制代码
# 匹配包含数字的行
grep "[[:digit:]]" /etc/passwd

# 匹配纯字母行
grep "^[[:alpha:]]*$" file.txt

2.4 重复量词(扩展正则)

量词 说明 示例
+ 1次或多次 a+ → "a", "aa"
? 0次或1次 colou?r → color, colour
{n} 恰好n次 \d{4} → 四位数字
{n,} 至少n次 \d{3,} → 至少三位数字
{n,m} n到m次 \d{2,4} → 2~4位数字

✅ 需使用 grep -Eegrep

bash 复制代码
# 匹配手机号(11位数字)
grep -E "^[1][3-9][0-9]{9}$" phones.txt

# 匹配IP地址(简化版)
grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" access.log

2.5 位置匹配

锚点 说明
^ 行首
$ 行尾
\b 单词边界
\B 非单词边界

✅ 示例:

bash 复制代码
# 匹配独立单词 root
grep "\broot\b" /etc/passwd

# 匹配行首空格
grep "^ " file.txt

2.6 子表达式和分支

语法 说明
(abc) 子表达式(分组)
`a(b c)d`

✅ 示例:

bash 复制代码
# 匹配 color 或 colour
grep -E "colou?r" file.txt   # ? 方式
grep -E "col(o|ou)r" file.txt # 分支方式

# 提取括号内内容(需 sed/awk)
echo "User: (John Doe)" | sed -n 's/.*(\(.*\)).*/\1/p'
# 输出:John Doe

2.7 回调引用(反向引用)

使用 \1, \2... 引用前面的子表达式
✅ 示例:

bash 复制代码
# 匹配重复单词(如 "the the")
echo "the the cat" | grep -E "\b([a-z]+) \1\b"

# 交换两个单词
echo "first second" | sed 's/\([a-z]*\) \([a-z]*\)/\2 \1/'
# 输出:second first

2.8 前后预查(零宽断言)

仅 Perl 正则支持(grep -P)

语法 说明
(?=exp) 正向先行断言(后面是exp)
(?!exp) 负向先行断言(后面不是exp)
(?<=exp) 正向后行断言(前面是exp)
(?<!exp) 负向后行断言(前面不是exp)

✅ 示例:

bash 复制代码
# 匹配后面跟着 .conf 的单词(但不包含 .conf)
echo "nginx.conf apache.conf" | grep -oP '\w+(?=\.conf)'
# 输出:nginx, apache

# 匹配前面是 /etc/ 的文件名
echo "/etc/passwd /tmp/file" | grep -oP '(?<=/etc/)\w+'
# 输出:passwd

2.9 回调条件(条件匹配)

Perl 正则高级功能

perl 复制代码
(?(condition)yes-pattern|no-pattern)

一般在 Perl 脚本中使用,shell 中较少用。


三、grep 正则表达式家族


3.1 grep 语法

✅ 基本语法:

bash 复制代码
grep [选项] 模式 [文件...]

✅ 常用选项:

选项 说明
-i 忽略大小写
-v 反向匹配(不包含)
-n 显示行号
-c 统计匹配行数
-l 只显示文件名
-r 递归搜索目录
-E 扩展正则(等价 egrep)
-P Perl 正则(功能最强)
-o 只显示匹配部分

3.2 grep 实例

✅ 案例1:搜索配置文件中的非注释非空行

bash 复制代码
grep -v "^#" /etc/ssh/sshd_config | grep -v "^$"

✅ 案例2:统计访问日志中 404 错误次数

bash 复制代码
grep " 404 " /var/log/nginx/access.log | wc -l

✅ 案例3:提取所有IP地址

bash 复制代码
grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}" access.log | sort | uniq -c

✅ 案例4:查找包含 root 或 admin 的行(忽略大小写)

bash 复制代码
grep -iE "root|admin" /etc/passwd

✅ 案例5:查找前后有空格的单词 "error"

bash 复制代码
grep -P "(?<=\s)error(?=\s)" app.log

四、sed 流编辑器


4.1 sed 语法

✅ 基本语法:

bash 复制代码
sed [选项] '命令' 文件

✅ 常用选项:

选项 说明
-n 静默模式(只输出p命令内容)
-i 直接修改文件(慎用!)
-e 多命令
-f 从脚本文件读取命令

4.2 sed 内部命令

命令 说明 示例
p 打印 sed -n '2p' file → 打印第2行
d 删除 sed '2d' file → 删除第2行
s/pattern/repl/flags 替换 sed 's/foo/bar/g'
g 全局替换 s///g
i 插入行前 2i\New Line
a 插入行后 2a\New Line
c 替换整行 2c\New Content
= 打印行号 sed '=' file
! 取反 1!d → 删除除第1行外所有行

4.3 sed 实例

✅ 案例1:替换文件中所有 "old" 为 "new"

bash 复制代码
sed 's/old/new/g' file.txt
# -i 参数直接修改文件(备份建议)
sed -i.bak 's/old/new/g' file.txt

✅ 案例2:删除空行

bash 复制代码
sed '/^$/d' file.txt

✅ 案例3:在匹配行后添加注释

bash 复制代码
sed '/^Listen /a # This is the main port' /etc/httpd/conf/httpd.conf

✅ 案例4:提取括号内内容

bash 复制代码
echo "Name: (John Doe), Age: (30)" | sed -n 's/.*(\([^)]*\)).*/\1/p'
# 输出:John Doe (只匹配第一个)
# 提取所有:
echo "Name: (John Doe), Age: (30)" | sed 's/[^()]*([^)]*)//g'

✅ 案例5:多命令处理

bash 复制代码
sed -e 's/foo/bar/g' -e '/^$/d' -e '1i\# Modified on '"$(date)" file.txt

五、Perl 一行式命令

✅ 语法:

bash 复制代码
perl -ne '命令' 文件     # 逐行处理
perl -pe '命令' 文件     # 逐行处理并打印
perl -i -pe '命令' 文件  # 直接修改文件

✅ 常用选项:

选项 说明
-n 循环读入每行(不自动打印)
-p 循环读入每行(自动打印)
-i 修改文件
-e 执行命令
-l 自动处理换行符

✅ 实例:

bash 复制代码
# 替换(类似 sed)
perl -pe 's/foo/bar/g' file.txt

# 删除空行
perl -ne 'print unless /^$/' file.txt

# 提取IP(使用正则)
perl -ne 'while(/(\d+\.\d+\.\d+\.\d+)/g){print "$1\n"}' access.log

# 统计单词频次
perl -ne 'for $word (split) { $count{$word}++ } END { for $w (keys %count) { print "$w: $count{$w}\n" } }' file.txt

六、cut 抽取字段

✅ 语法:

bash 复制代码
cut [选项] [文件]

✅ 常用选项:

选项 说明
-d C 分隔符为C
-f N 第N个字段
-c N-M 第N到M个字符

✅ 示例:

bash 复制代码
# 提取用户名和shell(: 分隔)
cut -d: -f1,7 /etc/passwd

# 提取第1-5字符
cut -c1-5 /etc/hosts

# 提取第2列到最后
cut -d' ' -f2- data.txt

七、awk 编程


7.1 awk 脚本基本结构

✅ 语法:

bash 复制代码
awk 'pattern { action }' file

✅ 完整结构:

awk 复制代码
BEGIN { 初始化 }
pattern { 每行处理 }
END { 结束处理 }

7.2 awk 的工作流程

  1. 执行 BEGIN 块(一次)
  2. 逐行读入文件,匹配 pattern,执行 action
  3. 执行 END 块(一次)

7.3 awk 内置变量(预定义变量)

变量 说明
$0 整行内容
$1,$2... 第1,2...字段
NF 字段数量
NR 当前行号(全局)
FNR 当前文件行号
FS 输入字段分隔符(默认空格)
OFS 输出字段分隔符(默认空格)
RS 输入记录分隔符(默认换行)
ORS 输出记录分隔符(默认换行)

✅ 示例:

bash 复制代码
# 打印行号和字段数
awk '{print NR, NF, $0}' /etc/passwd

# 打印最后一列
awk '{print $NF}' /etc/passwd

# 打印倒数第二列
awk '{print $(NF-1)}' /etc/passwd

7.4 自定义变量

bash 复制代码
awk 'BEGIN{sum=0} {sum+=$1} END{print "Total:", sum}' data.txt

7.5 将外部变量值传递给 awk

✅ 方法1:使用 -v

bash 复制代码
name="John"
awk -v user="$name" 'BEGIN{print "Hello, " user}'

✅ 方法2:作为参数(注意引号)

bash 复制代码
awk 'BEGIN{print "Hello, " ENVIRON["USER"]}'

7.6 awk 运算与判断

✅ 支持:+ - * / % > < >= <= == != && || !
✅ 示例:

bash 复制代码
# 计算大于100的数值之和
awk '$1 > 100 {sum += $1} END{print sum}' data.txt

# 多条件判断
awk '$1 > 50 && $2 < 100 {print $0}' data.txt

7.7 设置字段分隔符

✅ 方法1:-F

bash 复制代码
awk -F: '{print $1}' /etc/passwd

✅ 方法2:在 BEGIN 中设置 FS

bash 复制代码
awk 'BEGIN{FS=":"} {print $1}' /etc/passwd

✅ 方法3:正则分隔符

bash 复制代码
awk -F'[ :]' '{print $1, $2}' file.txt  # 空格或冒号分隔

7.8 流程控制语句

✅ if-else

bash 复制代码
awk '{if($1 > 50) print "High"; else print "Low"}' data.txt

✅ for 循环

bash 复制代码
awk 'BEGIN{for(i=1;i<=5;i++) print i}'

✅ while 循环

bash 复制代码
awk 'BEGIN{i=1; while(i<=5) {print i; i++}}'

7.9 数组的应用

✅ 关联数组(key-value)

bash 复制代码
# 统计每个用户的进程数
ps -ef | awk '{count[$1]++} END{for(user in count) print user, count[user]}'

# 排序输出(通过管道)
ps -ef | awk '{count[$1]++} END{for(user in count) print count[user], user}' | sort -nr

7.10 内置函数

✅ 字符串函数:

函数 说明
length(str) 长度
substr(str, start, len) 子串
index(str, sub) 查找位置
tolower(str) 转小写
toupper(str) 转大写

✅ 数学函数:

函数 说明
int(x) 取整
sqrt(x) 平方根
rand() 随机数

✅ 示例:

bash 复制代码
# 提取域名
echo "https://www.example.com/path" | awk '{print substr($0, index($0, "//")+2)}' | awk -F/ '{print $1}'

# 转换大小写
awk '{print toupper($1)}' file.txt

八、综合性实战案例


案例1:Web 访问日志分析(access.log)

目标:统计访问IP、状态码、URL频次、流量TOP10
✅ 假设日志格式:

复制代码
192.168.1.100 - - [16/Sep/2025:10:00:01 +0800] "GET /index.html HTTP/1.1" 200 1024

✅ 脚本:analyze-access.sh

bash 复制代码
#!/bin/bash
LOG="/var/log/nginx/access.log"

echo "=== TOP 10 IPs ==="
awk '{print $1}' "$LOG" | sort | uniq -c | sort -nr | head -10

echo -e "\n=== TOP 10 URLs ==="
awk '{print $7}' "$LOG" | sort | uniq -c | sort -nr | head -10

echo -e "\n=== Status Code Count ==="
awk '{print $9}' "$LOG" | sort | uniq -c | sort -nr

echo -e "\n=== TOP 10 Traffic (Bytes) ==="
awk '$10 ~ /^[0-9]+$/ {print $1, $7, $10}' "$LOG" | sort -k3nr | head -10

echo -e "\n=== 404 Errors ==="
grep " 404 " "$LOG" | awk '{print $7}' | sort | uniq -c | sort -nr

案例2:系统用户审计报告

目标:生成用户列表(UID>1000)、shell类型、家目录、最后登录
✅ 脚本:user-audit.sh

bash 复制代码
#!/bin/bash
echo "User Audit Report - $(date)"
echo "========================================"

awk -F: '$3 >= 1000 && $3 != 65534 {
    printf "%-15s %-10s %-20s %s\n", $1, $3, $6, $7
}' /etc/passwd

echo -e "\nShell Summary:"
cut -d: -f7 /etc/passwd | sort | uniq -c

echo -e "\nLast Login:"
last | awk 'NF>0 && $1 != "reboot" && $1 != "wtmp" {count[$1]++; lastseen[$1]=$4" "$5" "$6} END {
    for(user in count) {
        printf "%s: %d times, last: %s\n", user, count[user], lastseen[user]
    }
}' | sort

案例3:自动化配置文件清理器

目标:删除注释和空行,保留有效配置
✅ 脚本:clean-config.sh

bash 复制代码
#!/bin/bash
if [ $# -eq 0 ]; then
    echo "Usage: $0 <config_file>"
    exit 1
fi

FILE="$1"
BACKUP="${FILE}.bak.$(date +%Y%m%d)"

# 备份原文件
cp "$FILE" "$BACKUP"

# 清理:删除空行和#开头的行(允许行内注释)
grep -v "^[[:space:]]*#" "$FILE" | grep -v "^[[:space:]]*$" > "$FILE.tmp"

# 使用 awk 保留行内注释(# 前有非空字符)
awk '
{
    # 如果行内有 # 且前面有非空字符,则保留 # 前部分
    if (match($0, /[^#[:space:]]+#/)) {
        pos = RSTART + RLENGTH - 2  # # 前一个字符位置
        print substr($0, 1, pos)
    } else if ($0 !~ /^[[:space:]]*#/) {
        print $0
    }
}
' "$FILE.tmp" > "$FILE"

rm "$FILE.tmp"

echo "Cleaned: $FILE (backup: $BACKUP)"

案例4:日志实时监控 + 告警(awk + grep + mail)

✅ 脚本:monitor-log.sh

bash 复制代码
#!/bin/bash
LOG="/var/log/messages"
KEYWORDS=("ERROR" "CRITICAL" "FAILED" "DENIED")
EMAIL="admin@example.com"

tail -f "$LOG" | while read line; do
    for kw in "${KEYWORDS[@]}"; do
        if echo "$line" | grep -q "$kw"; then
            echo "[$(date)] $kw detected: $line" | mail -s "ALERT: $kw in $LOG" "$EMAIL"
            break
        fi
    done
done

✅ 后台运行:

bash 复制代码
nohup ./monitor-log.sh > /tmp/monitor.log 2>&1 &

✅ 本章小结 & 最佳实践

  1. 组合使用grep | sort | uniq | awk 是黄金组合
  2. 正则优先 :复杂匹配用 -P(Perl 正则)
  3. 安全第一sed -i 前先备份,或使用 -i.bak
  4. 性能考虑:大文件避免多次读取,用 awk 一次处理
  5. 可读性:复杂 awk 脚本写成文件,加注释
  6. 调试技巧awk '{print NR, $0}' 调试行号
  7. 编码注意 :处理中文用 LC_ALL=C.UTF-8

📚 附录:命令速查表

功能 命令
显示文件 cat -n file
前10行 head -n 10 file
后10行 tail -n 10 file
排序去重 `sort file
提取列 cut -d: -f1 /etc/passwd
替换文本 sed 's/old/new/g' file
匹配IP grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' file
统计字段和 awk '{sum+=$1} END{print sum}' file
传递变量 awk -v var="$shell_var" '...'

🧩 扩展项目建议

  1. 日志分析仪表盘:awk + gnuplot 生成图表
  2. 配置文件版本对比:diff + awk 高亮差异
  3. 自动化报表系统:cron + awk + mail
  4. 入侵检测脚本:监控日志 + 自动封IP
  5. 数据清洗管道:grep + sed + awk + sort + uniq

这份文档覆盖了 CentOS Stream 9 文本过滤器的全部核心知识点 + 语法细节 + 配置说明 + 实用脚本 + 综合项目,所有配置和代码均含详细注释,可直接用于教学、自学或生产环境参考。

相关推荐
deng-c-f8 小时前
Linux C/C++ 学习日记(51):内存池
jvm·学习
刘孬孬沉迷学习8 小时前
WebRTC 协议
学习·5g·webrtc·信息与通信·信号处理
丝斯20118 小时前
AI学习笔记整理(33)—— 视觉Transformer (ViT)与自注意力机制
人工智能·笔记·学习
【上下求索】8 小时前
学习笔记096——Windows postgreSQL-18.1[压缩包版本]
windows·笔记·学习·postgresql
AI视觉网奇8 小时前
Meta-Llama-3.1-8B-bnb-4bit 下载加载
linux·开发语言·python
学习3人组8 小时前
docker运行报错启动守护进程
linux·运维·centos
路在脚下,梦在心里8 小时前
net学习总结
android·学习
deng-c-f8 小时前
Linux C/C++ 学习日记(52):原子操作(1):cpu缓存、可见性、顺序性、内存序、缓存一致性的介绍
学习·原子操作
●VON8 小时前
小V健身助手开发手记(六):KeepService 的设计、实现与架构演进
学习·架构·openharmony·开源鸿蒙·von