Linux正则表达式与三剑客全攻略
Linux正则表达式与三剑客全攻略
一、概述
本文系统覆盖Linux正则表达式(基础/扩展/Perl/括号表达式)、三剑客(grep、Sed、Awk)及Linux特殊符号(引号、重定向、通配符)的全量知识点,包含正则匹配、文本处理、特殊符号应用、磁盘故障排查等核心内容。既适合运维新手从零入门,通过step-by-step实操掌握Linux文本处理与命令行核心技能,也可作为资深运维的复习参考,解决日志过滤、配置文件修改、数据提取、统计分析、脚本编写等日常工作场景。
二、核心知识点
2.1 正则表达式核心认知
2.1.1 正则分类与适用场景
| 正则类型 | 核心符号 | 支持工具 | 适用场景 |
|---|---|---|---|
| 基础正则(BRE) | ^ $ ^$ . \ * [] [^] .* |
grep、sed(默认)、awk | 简单文本过滤、日志匹配 |
| 扩展正则(ERE) | `+ | () {} ?` | egrep、grep -E、sed -r、awk |
| Perl正则(PRE) | \d \s \w \D \S \W |
grep -P | 快捷匹配(数字、空格、单词) |
| 括号表达式(POSIX) | [:alnum:] [:alpha:] [:digit:] [:blank:] |
grep、sed、awk | 标准化字符集匹配(跨locale兼容) |
2.1.2 基础正则核心符号(必掌握)
| 符号 | 含义 | 优先级 | 核心用途 |
|---|---|---|---|
^ |
匹配行开头 | ★★★★★ | 过滤以指定字符开头的行(如^root匹配root开头的行) |
$ |
匹配行结尾 | ★★★★★ | 过滤以指定字符结尾的行(如8$匹配以8结尾的行) |
^$ |
匹配空行 | ★★★★★ | 排除配置文件空行、日志空行 |
. |
匹配任意单个字符(不匹配空行) | ★★★★☆ | 模糊匹配单个字符(如oldb.y匹配oldboy、oldbey) |
\ |
转义字符 | ★★★★☆ | 取消特殊符号含义(如\.匹配实际的点号) |
* |
前一个字符出现0次或多次 | ★★★☆☆ | 匹配重复字符(如0*匹配0次或多次0) |
.* |
匹配所有字符(贪婪匹配) | ★★★★★ | 匹配任意内容(如.*am匹配到am为止的所有内容) |
[] |
匹配括号内任意单个字符 | ★★★★★ | 限定匹配范围(如[0-9]匹配数字、[a-Z]匹配大小写字母) |
[^] |
排除括号内字符 | ★★★☆☆ | 反向匹配(如[^abc]匹配除a、b、c外的字符) |
2.1.3 扩展正则核心符号(必掌握)
| 符号 | 含义 | 优先级 | 核心用途 |
|---|---|---|---|
+ |
前一个字符出现1次或多次 | ★★★★★ | 匹配连续重复字符(如0+匹配连续1个及以上0) |
| ` | ` | 逻辑“或” | ★★★★☆ |
() |
分组(整体匹配/后向引用) | ★★★★★ | 组合匹配、字段提取(如`(tree |
{n,m} |
前一个字符出现n到m次 | ★★★☆☆ | 精确控制重复次数(如0{3,5}匹配3-5个连续0) |
? |
前一个字符出现0次或1次 | ★★☆☆☆ | 可选字符匹配(如go?d匹配gd或god) |
2.1.4 Perl正则快捷符号(常用)
| 符号 | 等价于 | 含义 | 核心用途 |
|---|---|---|---|
\d |
[0-9] |
匹配数字 | 快速提取数字(如日志中的IP、端口) |
\s |
[\t\r\n\f ] |
匹配空字符(空格、制表符等) | 匹配空白内容 |
\w |
[0-9a-zA-Z_] |
匹配单词字符(数字、字母、下划线) | 提取单词、用户名等 |
\D |
[^0-9] |
匹配非数字 | 排除数字内容 |
\S |
[^[:space:]] |
匹配非空字符 | 排除空白内容 |
\W |
[^0-9a-zA-Z_] |
匹配非单词字符 | 排除单词字符 |
2.1.5 括号表达式(POSIX标准,了解)
| 表达式 | 等价于 | 含义 | 核心用途 |
|---|---|---|---|
[:alnum:] |
[0-9a-zA-Z] |
字母数字字符 | 跨locale兼容匹配字母和数字 |
[:alpha:] |
[a-zA-Z] |
字母字符 | 匹配大小写字母 |
[:digit:] |
[0-9] |
数字字符 | 匹配0-9数字 |
[:blank:] |
[ \t] |
空白字符(空格、制表符) | 匹配可见空白 |
[:cntrl:] |
- | 控制字符(ASCII 000-037、177) | 匹配控制字符(如DEL) |
2.2 三剑客核心认知
2.2.1 三剑客功能对比(选型指南)
| 工具 | 核心优势 | 擅长场景 | 不擅长场景 |
|---|---|---|---|
| grep/egrep | 过滤速度最快,正则匹配简洁 | 日志过滤、内容查找、条件筛选 | 字段提取、批量修改文件 |
| Sed | 支持行定位、替换、删除、后向引用 | 配置文件修改、行级批量处理、简单字段提取 | 复杂列操作、统计计算 |
| Awk | 强大的取行取列、统计计算、逻辑判断 | 字段提取、数据统计、格式整理、多条件筛选 | 大文件替换(效率低于Sed) |
2.2.2 Sed命令核心认知
-
定义:Stream Editor(流编辑器),用于文本的查找、替换、删除、新增、字段提取等操作,不默认修改原文件;
-
核心优势:支持正则匹配、行号定位、批量处理、后向引用,适合大文件和自动化脚本;
-
命令格式:
sed [选项] '条件 动作' 文件; -
常用选项:
-n:取消默认输出(仅显示匹配内容);-r:支持扩展正则(无需转义+|(){}?);-i:直接修改原文件(危险,建议先备份);-i.bak:修改前备份原文件(生成.bak备份文件,推荐生产环境使用);
-
核心动作:
动作 含义 核心用途 p打印匹配内容 查找并显示指定行/匹配内容 d删除匹配内容 删除空行、注释行、指定行 s/旧值/新值/g替换内容( g表示全局替换)批量修改配置参数、替换字符串 a在匹配行后新增内容 新增配置项、注释 i在匹配行前插入内容 插入说明、配置模板 c替换整行内容 批量替换指定行的全部内容 -
后向引用:通过正则分组
()捕获字段,再通过\数字引用分组内容,实现字段提取、重组(需配合sed -r)。
2.2.3 Awk命令核心认知
-
定义:一门处理文本的单行脚本语言,以“行”为处理单位,支持复杂的取行取列、统计计算、逻辑判断;
-
核心优势:取列能力强、支持自定义分隔符、可实现统计求和、多条件筛选,适合结构化文本处理;
-
命令格式:
awk [选项] '条件{动作}' 文件; -
常用选项:
-F:指定字段分隔符(默认以空白字符/连续空白字符/tab分隔);
-
核心变量:
变量 含义 核心用途 NR记录号(行号) 取指定行、行范围 NF每行的字段数 取最后一列( $NF)、倒数第N列($(NF-N))$0整行内容 输出整行 $n第n列内容(n为数字) 取指定列(如 $1取第1列、$3取第3列) -
常用运算符:
运算符 含义 示例 ==等于 $3==1000(第3列等于1000)!=不等于 $1!="root"(第1列不等于root)>大于 $3>1000(第3列大于1000)>=大于等于 $3>=1000(第3列大于等于1000)<小于 $3<1000(第3列小于1000)<=小于等于 $3<=1000(第3列小于等于1000)&&并且 $3>1000 && $1~"oldboy"(第3列大于1000且第1列包含oldboy)` ` -
匹配符:
~:包含匹配(如$4~ /^[01]/表示第4列以0或1开头);!~:不包含匹配(如$1!~ /root/表示第1列不包含root)。
2.3 Linux特殊符号核心认知
2.3.1 引号系列(字符串处理)
| 引号类型 | 核心特性 | 适用场景 | 示例 |
|---|---|---|---|
单引号(' ') |
所见即所得,不解析任何特殊符号 | 需原样输出字符串(含变量、命令) | echo '$(whoami) $UID' → 输出$(whoami) $UID |
双引号(" ") |
解析变量($)、命令替换($(...)),不解析通配符({}) |
需保留变量 / 命令结果,不扩展文件名 | echo "当前用户: $(whoami), UID: $UID" → 输出当前用户: root, UID: 0 |
| 不加引号 | 解析变量、命令替换、通配符 | 需扩展文件名、批量操作 | echo oldboy{1..3} → 输出oldboy1 oldboy2 oldboy3 |
| 反引号(``````) | 优先执行内部命令,返回执行结果(等价于$(...)) |
命令嵌套执行 | echo "当前目录: pwd" → 输出当前目录: /root |
2.3.2 重定向符号系列(IO流控制)
| 符号 | 含义 | 简写 | 应用场景 |
|---|---|---|---|
1> |
标准输出重定向(清空文件后写入) | > |
创建文件、覆盖写入内容 |
1>> |
标准输出追加重定向(写入文件末尾) | >> |
日志追加、配置文件补充 |
2> |
标准错误输出重定向(清空后写入错误信息) | - | 单独捕获错误信息 |
2>> |
标准错误追加重定向(错误信息追加到文件) | - | 持续捕获错误日志 |
>> 文件 2>&1 |
标准输出+错误输出合并追加重定向 | - | 脚本/定时任务日志(完整记录结果) |
&>> 文件 |
标准输出+错误输出合并追加重定向 | - | 简化写法,同>> 文件 2>&1 |
</0< |
标准输入重定向 | - | 搭配xargs、tr等命令读取文件 |
<</<<< |
here-document(多行输入重定向) | - | 批量写入多行内容到文件 |
2.3.3 通配符系列(文件匹配)
| 符号 | 含义 | 核心用途 | 示例 |
|---|---|---|---|
* |
匹配任意长度字符(含空字符) | 批量匹配文件名 | ls *.log → 匹配所有.log后缀文件 |
? |
匹配任意单个字符 | 精确长度文件名匹配 | ls /bin/?? → 匹配/bin目录下2个字符的命令 |
{} |
生成序列/枚举 | 批量创建文件、备份 | touch oldboy{1..5}.txt → 创建5个文件;cp oldboy.txt{,.bak} → 备份文件 |
[] |
匹配括号内任意单个字符 | 限定字符范围匹配 | ls oldboy[135].txt → 匹配oldboy1/3/5.txt |
[^]/[!] |
匹配括号外任意单个字符 | 反向匹配文件名 | ls oldboy[^0-9].txt → 匹配非数字结尾的文件 |
2.4 磁盘故障核心认知(补充场景)
2.4.1 故障场景:No space left on device
- 核心现象:系统提示“磁盘空间不足”,无法创建文件、写入日志;
- 排查方向:
- 磁盘空间满(
df -h查看); - inode节点耗尽(
df -i查看); - 文件已删除但进程未释放(
lsof | grep delete查看);
- 磁盘空间满(
- 解决思路:删除大文件/无用文件、释放占用进程、扩展磁盘空间。
三、步骤/命令
3.1 正则表达式实战命令
3.1.1 基础正则实操(grep命令)
# 环境准备:创建测试文件
cat > re.txt << EOF
I am oldboy teacher!
I teach linux.
I like badminton ball ,billiard ball and chinese chess!
my blog is http://oldboy.blog.51cto.com
our size is http://blog.oldboyedu.com
my qq is 49000448
not 4900000448.
my god ,i am not oldbey,but OLDBOY!
EOF
# 1. 匹配以my开头的行(^用法)
grep '^my' re.txt
# 输出:my blog is http://oldboy.blog.51cto.com、my qq is 49000448、my god ,i am not oldbey,but OLDBOY!
# 2. 匹配以8结尾的行($用法)
grep '8$' re.txt
# 输出:my qq is 49000448
# 3. 排除空行(^$用法)
grep -v '^$' /etc/ssh/sshd_config
# 输出:/etc/ssh/sshd_config中所有非空行
# 4. 匹配包含oldb+任意字符+y的行(.用法)
grep 'oldb.y' re.txt
# 输出:I am oldboy teacher!、my god ,i am not oldbey,but OLDBOY!
# 5. 匹配以点号结尾的行(\转义用法)
grep '\.$' re.txt
# 输出:I teach linux.、not 4900000448.
# 6. 匹配所有包含数字的行([]用法)
grep '[0-9]' re.txt
# 输出:包含QQ号、网址端口的行
# 7. 匹配以m或n开头的行([]+^用法)
grep '^[mn]' re.txt
# 输出:my开头和not开头的行
3.1.2 扩展正则实操(egrep/grep -E)
# 1. 匹配连续出现的0(+用法)
egrep '0+' re.txt
# 输出:my qq is 49000448、not 4900000448.
# 2. 匹配包含oldboy或linux的行(|用法)
egrep 'oldboy|linux' re.txt
# 输出:I am oldboy teacher!、I teach linux.、my blog is http://oldboy.blog.51cto.com等
# 3. 匹配tree、vim或sl软件是否安装(()用法)
rpm -qa | egrep '(tree|vim|sl)'
# 输出:已安装的tree、vim、sl相关软件包
# 4. 匹配3-5个连续的0({}用法)
egrep '0{3,5}' re.txt
# 输出:my qq is 49000448(包含3个0)
# 5. 匹配身份证号(18位,最后一位为数字或X)
cat > id.txt << EOF
230189199012251659
23018219590413055X
23018219610227185
EOF
egrep '[0-9]{17}[0-9X]$' id.txt
# 输出:前两条符合18位身份证规则的记录
3.1.3 Perl正则与括号表达式实操
# 1. Perl正则:快速匹配所有数字(\d用法)
grep -P '\d' re.txt
# 输出:包含数字的行(QQ号、网址)
# 2. 括号表达式:匹配字母数字字符([:alnum:]用法)
grep '[[:alnum:]]' re.txt
# 输出:包含字母或数字的所有行(等价于grep '[a-zA-Z0-9]' re.txt)
# 3. 括号表达式:匹配空白字符([:blank:]用法)
grep '[[:blank:]]' re.txt
# 输出:包含空格或制表符的行
3.2 Sed命令实战操作
3.2.1 Sed查找与打印(p动作)
# 环境准备:创建测试文件
cat > sed.txt << EOF
101,oldboy,CEO
102,bigbao,CTO
103,李导996,COO
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
EOF
# 1. 打印第3行(行号定位)⭐️
sed -n '3p' sed.txt
# 输出:103,李导996,COO
# 2. 打印第2-5行(行号范围)⭐️
sed -n '2,5p' sed.txt
# 输出:第2到第5行内容
# 3. 打印包含oldboy的行(正则匹配)⭐️
sed -n '/oldboy/p' sed.txt
# 输出:101,oldboy,CEO
# 4. 打印从包含bigbao的行到包含lidao的行(范围匹配)
sed -n '/bigbao/,/lidao/p' sed.txt
# 输出:102,bigbao,CTO到110,lidao,COCO之间的所有行
# 5. 打印第3行和第5行(指定多行)
sed -n '3p;5p' sed.txt
# 输出:103,李导996,COO、105,feixue,CIO
# 6. 打印奇数行(规律查找)
seq 10 | sed -n '1~2p'
# 输出:1、3、5、7、9
# 7. 过滤日志时间范围(实战场景)
# 提取access.log中11:05到11:06的日志
sed -n '/2015:11:05:00/,/2015:11:06:00/p' access.log | wc -l
# 输出:符合时间范围的日志条数
3.2.2 Sed替换操作(s动作)
# 1. 将lidao替换为oldboy(全局替换)⭐️
sed 's#lidao#oldboy#g' sed.txt
# 说明:s=替换,#=分隔符(可替换为/或@),g=全局替换
# 输出:110,oldboy,COCO(lidao已替换为oldboy)
# 2. 直接修改原文件并备份(推荐生产环境)⭐️
sed -i.bak 's#bigbao#oldbao#g' sed.txt
# 说明:-i.bak会生成sed.txt.bak备份文件,修改原文件
cat sed.txt
# 输出:102,oldbao,CTO(bigbao已替换为oldbao)
# 3. 替换配置文件中的注释行(结合正则)
# 排除/etc/ssh/sshd_config中的空行和注释行,替换Port为2222
sed -i 's#^Port 22#Port 2222#g' /etc/ssh/sshd_config
grep -v '^$' /etc/ssh/sshd_config | grep -v '^#' | grep Port
# 输出:Port 2222
3.2.3 Sed后向引用(进阶提取)⭐️
# 环境准备:复制passwd文件用于测试
cp /etc/passwd ./test_passwd
# 1. 案例1:调换test_passwd第1列(用户名)和最后1列(Shell)的顺序
sed -r 's#^(.*)(:x.*:)(.*$)#\3\2\1#g' test_passwd
# 说明:
# ^(.*):第1组,匹配用户名(行开头到第一个:前的内容)
# (:x.*:):第2组,匹配中间部分(从:x到最后一个:的内容)
# (.*$):第3组,匹配Shell路径(最后一个:到行尾)
# \3\2\1:引用分组内容,调换第1组和第3组顺序
# 输出:/bin/bash:x:0:0:root:/root:root(用户名和Shell已调换)
# 2. 案例2:提取eth0网卡的IP地址
ip a s eth0 | sed -nr '3s#^.*et ([0-9.]+)/.*$#\1#gp'
# 说明:
# -n:取消默认输出,-r:支持扩展正则
# 3:定位第3行(IP所在行)
# ^.*et ([0-9.]+)/.*$:匹配IP地址(数字+点号组合)并分组
# \1:引用分组的IP地址,p:打印结果
# 输出:10.0.0.200(网卡eth0的IP地址)
# 3. 案例3:提取文件权限(如stat /etc/hosts中的0644)
stat /etc/hosts | sed -nr '4s#^.*\(([0-9]+)/.*$#\1#gp'
# 输出:0644(/etc/hosts的文件权限)
3.2.4 Sed删除与新增操作(d/a/i/c动作)
# 1. 删除操作(d动作)
# 1.1 删除sed.txt第4行
sed -i '4d' sed.txt
cat sed.txt
# 输出:第4行(104,yy,CFO)已删除
# 1.2 删除包含feixue的行
sed -i '/feixue/d' sed.txt
cat sed.txt
# 输出:包含feixue的行已删除
# 1.3 删除空行和以#开头的注释行(配置文件清理)⭐️
sed -r '/^$|^#/d' /etc/ssh/sshd_config > sshd_config.clean
# 输出:生成无空行、无注释的干净配置文件
# 2. 新增操作(a/i动作)
# 2.1 在第3行后新增内容(a动作)
sed '3a 999,lidao007,UFO' sed.txt
# 输出:第3行后新增999,lidao007,UFO
# 2.2 在第3行前插入内容(i动作)
sed '3i 999,lidao007,UFO' sed.txt
# 输出:第3行前插入999,lidao007,UFO
# 3. 替换整行内容(c动作)
sed '3c 999,lidao007,UFO' sed.txt
# 输出:第3行内容替换为999,lidao007,UFO
3.3 Awk命令实战操作
3.3.1 Awk取行操作(NR变量)⭐️
# 1. 取第1行
awk 'NR==1 {print $0}' /etc/passwd
# 输出:/etc/passwd第1行(root:x:0:0:root:/root:/bin/bash)
# 2. 取第2-5行
awk 'NR>=2 && NR<=5 {print $0}' /etc/passwd
# 输出:/etc/passwd第2到第5行内容
# 3. 取包含root或nobody的行(正则匹配)
awk '/root|nobody/ {print $0}' /etc/passwd
# 输出:包含root或nobody的所有行
# 4. 取从包含root的行到包含nobody的行(范围匹配)
awk '/root/,/nobody/ {print $0}' /etc/passwd
# 输出:从root行到nobody行之间的所有行
3.3.2 Awk取列操作($n/NF变量)⭐️
# 1. 取ls -lh结果的大小列(第5列)和文件路径列(最后一列)
ls -lh /etc/ | awk '{print $5,$NF}' | column -t
# 说明:$5=第5列(大小),$NF=最后一列(文件路径),column -t对齐输出
# 输出:对齐后的文件大小和路径列表
# 2. 取/etc/passwd的第1列(用户名)、第3列(UID)、最后一列(Shell)
awk -F':' '{print $1,$3,$NF}' /etc/passwd | column -t
# 说明:-F':'指定分隔符为冒号,适配/etc/passwd格式
# 输出:对齐后的用户名、UID、Shell路径
# 3. 提取eth0网卡IP地址(复杂分隔符)
# 方法1:指定分隔符为空格或/(连续符号合并)
ip a s eth0 | awk -F'[ /]+' 'NR==3 {print $3}'
# 说明:NR==3定位IP所在行,-F'[ /]+'表示以空格或/为分隔符(连续符号算一个)
# 输出:10.0.0.200
# 方法2:双分隔符截取
ip a s eth0 | awk -F 'inet |/24' 'NR==3 {print $2}'
# 说明:以"inet "或"/24"为分隔符,直接截取IP部分
# 输出:10.0.0.200
3.3.3 Awk取行+取列(多条件筛选)⭐️
# 1. 取/etc/passwd中UID(第3列)大于1000的行,输出用户名和UID
awk -F':' '$3>1000 {print $1,$3}' /etc/passwd | column -t
# 说明:$3>1000为条件(UID大于1000),动作是打印第1列和第3列
# 输出:普通用户的用户名和对应的UID
# 2. 筛选第4列(GID)以0或1开头的行,输出用户名、UID、GID
awk -F':' '$4 ~ /^[01]/ {print $1,$3,$4}' /etc/passwd | column -t
# 说明:$4 ~ /^[01]/表示第4列以0或1开头,~为包含匹配符
# 输出:GID以0或1开头的用户信息
# 3. 监控swap使用(超过0则报警)
free | awk '/Swap:/ {if($3>0) print "异常:系统开始占用swap,系统异常,请排查"}'
# 说明:/Swap:/匹配Swap行,if($3>0)判断已使用swap大于0,执行打印报警信息
# 输出:若swap占用>0,显示报警信息
3.3.4 Awk统计与计算⭐️
# 1. 统计/etc/passwd的总行数(计数)
awk '{i=i+1} END{print "总行数:"i}' /etc/passwd
# 说明:i=i+1累加计数,END{}在处理完所有行后执行
# 输出:总行数:XX(实际行数)
# 2. 计算1-10的总和
seq 10 | awk '{sum=sum+$1} END{print "总和:"sum}'
# 说明:sum=sum+$1累加每行第1列,END{}输出结果
# 输出:总和:55
# 3. 统计日志中密码错误的IP出现次数(基础统计)
grep 'failed' /var/log/secure | awk '{print $(NF-3)}' | sort | uniq -c
# 说明:先提取错误IP(倒数第4列),再排序去重统计次数
# 输出:IP出现次数和对应IP
3.4 特殊符号实战操作
3.4.1 引号系列实操
# 1. 单引号(所见即所得)
echo '当前用户: $(whoami), UID: $UID, 序列: {1..5}'
# 输出:当前用户: $(whoami), UID: $UID, 序列: {1..5}
# 2. 双引号(解析变量和命令)
echo "当前用户: $(whoami), UID: $UID, 序列: {1..5}"
# 输出:当前用户: root, UID: 0, 序列: {1..5}({1..5}不解析)
# 3. 不加引号(解析变量、命令和通配符)
echo 当前用户: $(whoami), UID: $UID, 序列: {1..5}
# 输出:当前用户: root, UID: 0, 序列: 1 2 3 4 5
# 4. 反引号(命令替换)
echo "当前目录: `pwd`, 系统时间: `date +%Y-%m-%d`"
# 输出:当前目录: /root, 系统时间: 2024-05-20
3.4.2 重定向符号实操⭐️
# 1. 标准输出重定向(覆盖写入)
echo "Hello Linux" > test.txt
cat test.txt
# 输出:Hello Linux
# 2. 标准输出追加重定向(追加写入)
echo "Hello Oldboy" >> test.txt
cat test.txt
# 输出:Hello Linux、Hello Oldboy
# 3. 错误输出重定向(捕获错误)
eco "Test Error" 2> error.txt # eco为错误命令
cat error.txt
# 输出:-bash: eco: command not found
# 4. 合并输出(标准+错误)
echo "正常内容" &>> all.log
eco "错误内容" &>> all.log
cat all.log
# 输出:正常内容、-bash: eco: command not found
# 5. 多行写入文件(here-document)⭐️
cat > oldboy.txt << EOF
I love Linux
I like oldboyedu
Today is a good day
EOF
cat oldboy.txt
# 输出:3行写入内容
# 6. 输入重定向(搭配xargs)
echo -e "1 2 3\n4 5 6\n7 8 9" > num.txt
xargs -n3 < num.txt # 按3个一组输出
# 输出:1 2 3、4 5 6、7 8 9
3.4.3 通配符实操⭐️
# 1. *匹配任意文件
ls *.txt
# 输出:当前目录下所有.txt后缀文件
# 2. ?匹配单个字符
ls /bin/??
# 输出:/bin目录下2个字符的命令(如ls、cp、mv)
# 3. {}生成序列/枚举
# 生成数字序列
echo {1..10} # 输出:1 2 ... 10
echo {01..10} # 输出:01 02 ... 10(等宽数字)
# 生成字符序列
echo {a..z..2} # 输出:a c e ... y(步长2)
# 批量创建文件
touch oldboy{1..5}.log
# 生成:oldboy1.log到oldboy5.log
# 批量备份文件
cp oldboy.txt{,.bak}
# 等价于:cp oldboy.txt oldboy.txt.bak
# 4. []限定字符范围
ls oldboy[135].log
# 输出:oldboy1.log、oldboy3.log、oldboy5.log
# 5. [^]反向匹配
ls oldboy[^0-9].log
# 输出:非数字结尾的oldboy*.log文件
3.5 磁盘故障排查实操(No space left on device)
# 1. 故障复现:模拟磁盘空间满
dd if=/dev/zero of=/test.img bs=1G count=10 # 生成10G大文件,填满磁盘
touch /test.txt # 提示:No space left on device
# 2. 排查步骤
# 2.1 检查磁盘空间
df -h
# 输出:/分区使用率100%
# 2.2 检查inode节点(排除inode耗尽)
df -i
# 输出:inode使用率正常
# 2.3 查找大文件(逐层排查)
du -sh //* | sort -rh | head -10 # 查找根目录下最大的10个文件
# 输出:/test.img占用10G
# 2.4 检查已删除但未释放的文件
lsof | grep delete
# 输出:无此类文件(若有,需重启对应进程释放)
# 3. 解决方案
rm -rf /test.img # 删除大文件
touch /test.txt # 可正常创建,故障解决
四、原理说明
4.1 正则表达式匹配原理
- 贪婪匹配:正则默认“尽可能多匹配”,如
.*o会匹配从开头到最后一个o的所有内容(而非第一个o); - 匹配顺序:从左到右逐字符匹配,遇到符合条件的内容即记录,直到行尾;
- 符号优先级:分组
()> 重复*+?{}> 连接(如oldboy) > 或|; - 中括号特性:
[]内的特殊符号(如*、.)会自动失去特殊含义,无需转义(如[.*]匹配实际的.或*); - 括号表达式原理:遵循POSIX标准,跨locale环境兼容,避免因字符编码差异导致匹配失败(如
[:alnum:]在不同系统中均匹配字母数字)。
4.2 三剑客工作原理
4.2.1 Sed命令工作原理
- 读取行:Sed从输入文件/流中逐行读取内容,存入缓冲区(模式空间);
- 处理行:根据指定的“条件+动作”处理缓冲区中的行(如匹配正则后打印、替换、提取);
- 输出行:处理完成后,将缓冲区中的行输出到屏幕(
-n选项会关闭默认输出,仅输出匹配行); - 循环执行:重复上述步骤,直到所有行处理完毕;
- 修改文件:默认不修改原文件,
-i选项会将缓冲区的修改写入原文件,-i.bak会先备份再修改。
4.2.2 Awk命令工作原理
- 初始化:读取命令行选项和模式动作,准备处理;
- 读取行:逐行读取输入文件/流,自动按指定分隔符分割字段(默认空白字符);
- 设置变量:为每行设置NR(行号)、NF(字段数)、$0(整行)、$n(第n列)等变量;
- 条件判断:判断当前行是否满足“条件”,满足则执行对应的“动作”;
- 循环执行:重复步骤2-4,直到所有行处理完毕;
- 收尾执行:若有END{}块,执行收尾操作(如输出统计结果)。
4.3 特殊符号工作原理
4.3.1 引号解析原理
- Shell执行命令时,会先解析引号内的内容:单引号完全不解析,双引号解析变量和命令替换,不加引号额外解析通配符;
- 反引号与
$(...)等价,属于命令替换,Shell会先执行内部命令,将结果替换回命令行再执行整体命令。
4.3.2 重定向原理
- Linux中每个进程默认打开3个文件描述符:0(标准输入)、1(标准输出)、2(标准错误输出);
- 重定向符号通过修改文件描述符的指向,改变输入/输出的来源/目标(如
> file将1指向file,2>&1将2指向1的目标)。
4.3.3 通配符匹配原理
- 通配符由Shell解析(而非命令本身),Shell先扩展通配符为匹配的文件名列表,再将列表作为参数传递给命令;
- 通配符匹配优先级:
*/?>[]/[^]>{},仅匹配文件名,不匹配文件内容(与正则区分)。
4.4 磁盘故障原理
- 磁盘空间满:物理存储空间耗尽,无法写入新数据,需删除无用文件释放空间;
- inode耗尽:每个文件/目录占用一个inode节点,若大量小文件导致inode用尽,即使有磁盘空间也无法创建文件;
- 文件已删除但进程未释放:文件被删除但仍被进程占用,磁盘空间未实际释放,需重启进程或发送信号让进程释放。
五、注意事项
-
正则符号注意:
- 所有正则符号均为英文符号,避免使用中文符号(如中文的
。代替.); - 转义字符
\仅在基础正则中需要(如\(),扩展正则(sed -r/egrep/awk)中无需转义+|(){}?; - 正则与通配符区分:正则用于匹配文件内容,通配符用于匹配文件名,避免混淆(如
*在正则中表示重复,在通配符中表示任意字符)。
- 所有正则符号均为英文符号,避免使用中文符号(如中文的
-
三剑客选型注意:
- 单纯过滤内容(如日志筛选):优先选grep/egrep(速度最快);
- 行级修改(如配置文件替换、删除行):优先选Sed;
- 字段提取、统计计算、多条件筛选:优先选Awk;
- 复杂场景可组合使用(如
grep 筛选 | awk 取列 | sort 排序)。
-
特殊符号注意:
- 重定向
>会覆盖文件内容,使用前需确认文件是否有用,避免误删数据; - here-document的结束标记(如EOF)需单独一行,前后不能有多余空格或字符;
- 通配符
*在空目录下会原样输出(如ls *.txt输出*.txt),可结合shopt -s nullglob优化(空匹配时不输出)。
- 重定向
-
磁盘故障排查注意:
- 执行
rm -rf删除大文件时,需确认文件路径正确,避免误删系统核心文件; - 排查inode耗尽时,需查找大量小文件(如/tmp目录下的临时文件),删除后释放inode;
- 生产环境建议定期清理日志、临时文件,避免磁盘空间满导致服务故障。
- 执行
六、总结与避坑指南
6.1 总结
本文整合四份PDF全量内容,构建了Linux文本处理与系统运维的完整技术体系,核心覆盖四大模块:
- 正则表达式:文本匹配的基础,提供精准的内容定位能力,适配不同场景的匹配需求;
- 三剑客工具:grep(过滤)、Sed(修改)、Awk(分析),解决文本处理的核心需求;
- 特殊符号:引号(字符串处理)、重定向(IO控制)、通配符(文件匹配),提升命令行与脚本效率;
- 故障排查:磁盘空间不足故障的复现、排查与解决,覆盖运维常见场景。
核心原则:文本处理的核心是“精准匹配+高效处理”,特殊符号是“效率提升工具”,故障排查是“运维必备技能”,三者结合可解决Linux系统中绝大多数文本与基础运维问题,是运维新手入门与资深运维提升的核心知识点。
6.2 避坑指南
| 坑点 | 解决方案 |
|---|---|
正则与通配符混淆(如用*匹配文件内容) |
明确场景:匹配文件内容用正则,匹配文件名用通配符 |
Sed替换时包含/导致语法错误 |
切换分隔符,如sed 's#http://#https://#g' file |
重定向>误覆盖重要文件 |
优先使用>>追加,或备份文件(cp file file.bak) |
| Awk取列时分隔符错误导致列错位 | 用-F指定正确分隔符,复杂场景用正则(如-F'[ /]+') |
| 通配符在空目录下原样输出 | 开启shopt -s nullglob,空匹配时不输出通配符本身 |
| 磁盘故障排查时误删核心文件 | 删除文件前用ls验证路径,生产环境开启文件备份 |
双引号中{}不解析 |
不加引号或用eval(如eval echo "序列: {1..5}") |
行尾空格导致正则匹配失败(如^root $) |
用^root[[:space:]]*$匹配含空格的行尾 |
| Sed后向引用无法生效 | 忘记加-r选项,需执行sed -r 's#(分组)#\1#g' file |
| inode耗尽导致无法创建文件 | 用df -i排查,删除大量小文件(如rm -rf /tmp/*) |

浙公网安备 33010602011771号