Linux 通配符与正则表达式(含实战案例+避坑指南)
Linux 通配符与正则表达式全教程(含实战案例+避坑指南)
在Linux运维与开发中,通配符与正则表达式是提升效率的核心工具。前者快速定位文件,后者精准处理文本,二者常被混淆却有着本质区别。本文基于CentOS 7环境,系统梳理语法规则、实战技巧与避坑要点,所有命令均经过验证可直接复现。
一、核心区分:通配符 vs 正则表达式
初学者最易混淆二者,关键差异体现在匹配目标与解析逻辑上,具体对比如下:
维度 | 通配符(Wildcard) | 正则表达式(Regular Expression) |
---|---|---|
核心用途 | 匹配文件名/目录名(找文件) | 匹配/提取/替换文本内容(处理文件内数据) |
解析主体 | Shell(Bash)直接解析 | 文本工具(grep、sed、awk等)解析 |
匹配单位 | 以字符为单位,不支持复杂逻辑组合 | 以模式为单位,支持分组、逻辑运算等复杂规则 |
转义规则 | 仅特殊字符需转义(如* 、? ) | 大量元字符需转义(如^ 、$ 、. 等) |
典型工具 | ls 、find 、cp 、rm 、mv | grep (-E/-P)、sed (-r)、awk 、vim |
实操示例 | find /var -name 's*[0-9]*.log' (找日志文件) | grep -E '1[3-9][0-9]{9}' test.txt (提手机号) |
二、通配符:文件定位的高效利器
通配符由Shell解析,用于快速匹配文件路径,核心价值是简化文件操作。按功能可分为基础通配符、字符类与扩展用法三类。
2.1 通配符完整语法表
类别 | 符号/语法 | 作用描述 | 实操示例(含执行效果) |
---|---|---|---|
基础通配符 | * | 匹配任意长度字符(0个或多个,不匹配隐藏文件) | ls /var/log/*.log → 输出:/var/log/messages.log /var/log/secure.log |
? | 匹配单个任意字符 | ls /etc/ifcfg-eth? → 输出:/etc/ifcfg-eth0 | |
[abc] | 匹配方括号内任意一个字符 | ls /dev/sd[a-d] → 输出:/dev/sda /dev/sdb /dev/sdc /dev/sdd | |
[!abc] /[^abc] | 排除方括号内字符,匹配其他字符 | ls /tmp/[!0-9]* → 输出:/tmp/backdoor.sh /tmp/test.txt (排除数字开头文件) | |
[a-z] /[0-9] | 匹配区间内字符(字母/数字) | ls file[1-5].txt → 输出:file1.txt file2.txt file3.txt file4.txt file5.txt | |
Unix字符类 | [[:upper:]] | 所有大写字母(A-Z) | find /opt -name '[[:upper:]]*.sh' → 输出:/opt/BACKDOOR.sh |
[[:lower:]] | 所有小写字母(a-z) | ls [[:lower:]]*.conf → 输出:nginx.conf mysql.conf | |
[[:digit:]] | 所有数字(0-9) | ls log_[[:digit:]].txt → 输出:log_1.txt log_2.txt | |
[[:alpha:]] | 所有字母(大小写) | ls [[:alpha:]]*.sh → 输出:Test.sh init.sh | |
路径符号 | ~ | 当前用户家目录 | cd ~ && pwd → 输出:/root (root用户) |
- | 上一次工作目录 | cd /var/log && cd - → 输出:/root | |
. | 当前目录;隐藏文件前缀 | ls -a ~ → 输出:.bashrc .ssh .bash_history | |
.. | 上一级目录 | cd /var/log/nginx && cd .. && pwd → 输出:/var/log | |
扩展用法 | {,suffix} | 批量添加后缀(备份常用) | cp /etc/hosts{,.bak} → ls /etc/hosts* 输出:/etc/hosts /etc/hosts.bak |
{prefix,} | 批量添加前缀 | mv {a,b,c}.txt doc_{a,b,c}.txt → 生成doc_a.txt 等文件 | |
** (需启用globstar) | 递归匹配所有子目录文件(Bash 4.0+) | shopt -s globstar && ls **/*.txt → 输出所有子目录的.txt文件 |
注:
globstar
默认禁用,永久启用需添加shopt -s globstar
到~/.bashrc
。
2.2 高频实战练习题(含解析)
测试环境:CentOS 7,root用户,默认系统路径。
1. 找出/var
下以s
开头、任意小写字母结尾,中间至少1位数字的文件
核心思路:用*
匹配中间任意字符,[0-9]
确保数字存在,[a-z]
限定结尾。
解法1(基础语法):
find /var -type f -name 's*[0-9]*[a-z]'
解法2(标准字符类):
find /var -type f -name 's*[[:digit:]]*[[:lower:]]'
执行效果:
/var/lib/docker/overlay2/xxx/diff/usr/bin/sha1sum
/var/log/sa/sa25
2. 递归查找所有目录中以.conf
结尾的文件(两种方案对比)
方案1(globstar快速版):
shopt -s globstar && ls **/*.conf
方案2(find通用版,兼容旧系统):
find / -type f -name '*.conf' 2>/dev/null # 重定向错误输出避免权限提示
核心差异:globstar纯Shell解析,比find快2-5倍,但不支持文件属性过滤。
3. 批量创建按日期命名的日志目录(2024年1-3月)
命令:
mkdir -p /var/log/app/{202401,202402,202403}
# 或用序列扩展(Bash 4.0+)
mkdir -p /var/log/app/2024{01..03}
验证效果:
ls /var/log/app/
# 输出:202401 202402 202403
4. 备份/var/log/nginx/
下7天前的所有日志文件
命令:
find /var/log/nginx/ -name '*.log' -mtime +7 -exec cp {} {}.old \;
解析:-mtime +7
筛选7天前修改的文件,{}
代表匹配的文件名。
三、正则表达式:文本处理的精准工具
正则表达式用于匹配文本内容,按解析引擎分为基础正则(BRE)和扩展正则(ERE),后者支持更丰富的语法且无需大量转义。
3.1 前置准备:字符集配置
正则易受系统编码影响,建议先统一字符集:
export LC_ALL=C # 强制使用POSIX字符集,避免中文等特殊字符干扰
3.2 正则语法全表(BRE vs ERE)
3.2.1 基础正则(BRE,grep
默认支持)
元字符 | 作用描述 | 示例(匹配目标) | 实操效果(基于test.txt) |
---|---|---|---|
^ | 匹配行首 | ^I (以I开头的行) | grep -n '^I' test.txt → 输出:1:I am teacher zack. |
$ | 匹配行尾 | u$ (以u结尾的行) | grep -n 'u$' test.txt → 输出:8:#my site is https://www.cnblogs.com/pyyu |
. | 匹配任意单个字符(除换行) | f.l (f和l之间1个任意字符) | grep -n 'f.l' test.txt → 输出:无匹配 |
* | 匹配前面字符0次或多次 | ab*c (ac、abc、abbc等) | grep -n 'ab*c' test.txt → 输出:无匹配 |
[] | 匹配方括号内任意字符 | [0-9] (单个数字) | grep -n '[0-9]' test.txt → 输出含数字的行 |
[^] | 排除方括号内字符 | [^a-z] (非小写字母) | grep -n '[^a-z]' test.txt → 输出含非小写字母的行 |
\ | 转义特殊字符 | \.$ (以.结尾的行) | grep -n '\.$' test.txt → 输出:1:I am teacher zack. |
.* | 匹配任意长度字符(贪婪模式) | a.*b (a到b之间所有内容) | grep -n 'h.*o' test.txt → 输出:1:I am teacher zack. |
3.2.2 扩展正则(ERE,grep -E
/sed -r
支持)
元字符 | 作用描述 | 示例(匹配目标) | 实操效果(基于test.txt) |
---|---|---|---|
+ | 匹配前面字符1次或多次 | ab+c (abc、abbc等,不含ac) | grep -En 'tt+' test.txt → 输出:3:testtttsss000123566666 |
? | 匹配前面字符0次或1次 | colou?r (color、colour) | grep -En 'http?' test.txt → 输出:7:$my blog is http://www.zackit.cn |
{n} | 匹配前面字符恰好n次 | [0-9]{11} (11位手机号) | grep -En '[0-9]{11}' test.txt -o → 输出:10:15210888008 |
{n,} | 匹配前面字符至少n次 | [0-9]{8,} (8位及以上数字) | grep -En '[0-9]{8,}' test.txt -o → 输出:9:877348180 |
{n,m} | 匹配前面字符n到m次 | [a-z]{2,4} (2-4个连续小写字母) | grep -En '[a-z]{2,4}' test.txt → 输出含对应字符的行 |
` | ` | 逻辑或(匹配多个模式) | `http |
() | 分组(视为整体处理) | `g(la | oo)d`(glad或good) |
\n | 反向引用第n个分组 | ([a-z])\1 (连续2个相同小写字母) | grep -En '([a-z])\1' test.txt → 输出:3:testtttsss000123566666 |
(?=...) | 正向前瞻(后面必须跟指定内容) | 1[3-9][0-9]{8}(?=[0-9]) (11位手机号) | 同[0-9]{11} 效果,用于精准边界匹配 |
注:Perl正则(
grep -P
)支持更多高级语法(如\d
匹配数字、\b
单词边界),但兼容性稍差。
3.3 测试数据与实战练习
测试数据(保存为test.txt
):
I am teacher zack.
I teach linux,python.
testtttsss000123566666I like video,games,girls
#I like girls.
$my blog is http://www.zackit.cn
#my site is https://www.cnblogs.com/pyyu
My qq num is 877348180.
my phone num is 15210888008.
1. 提取所有URL(含http/https)
命令:
grep -Eo 'http[s]?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' test.txt
解析:[a-zA-Z0-9.-]
匹配域名主体,[a-zA-Z]{2,}
匹配后缀(如cn、com)。
执行效果:
http://www.zackit.cn
https://www.cnblogs.com
2. 匹配符合yyyy-mm-dd
格式的日期(假设文本含日期)
命令:
grep -Eo '20[0-9]{2}-[01][0-9]-[0-3][0-9]' test.txt
解析:分三段匹配,确保月份1-12、日期1-31的格式合法性。
3. 用sed替换所有旧域名为新域名
需求:将zackit.cn
替换为newdomain.com
命令:
sed -r 's/zackit\.cn/newdomain\.com/g' test.txt
解析:s/旧/新/g
是替换语法,.
需转义,g
表示全局替换。
执行效果:
$my blog is http://www.newdomain.com
4. 用awk统计文本中数字出现的总行数
命令:
awk '/[0-9]/{count++} END{print "含数字的行数:"count}' test.txt
解析:awk按行处理,/[0-9]/
匹配含数字的行,END
块输出统计结果。
执行效果:
含数字的行数:3
四、工具选型:grep/sed/awk 适用场景对比
正则的威力需结合工具发挥,三者核心定位不同,搭配使用可解决90%的文本处理需求:
工具 | 核心定位 | 优势场景 | 示例命令(提取手机号) |
---|---|---|---|
grep | 文本查找/过滤 | 快速匹配行、提取关键字 | grep -Eo '1[3-9][0-9]{9}' test.txt |
sed | 文本编辑(替换/删除) | 批量修改、按模式删除行 | sed -r 's/1[3-9][0-9]{9}/[手机号]/g' test.txt |
awk | 格式化处理(字段级) | 数据提取、统计、格式化输出 | awk '/1[3-9][0-9]{9}/{print $NF}' test.txt |
实战技巧:
grep
找位置,sed
改内容,awk
做统计,三者可通过管道组合使用(如grep | sed | awk
)。
五、运维高频实战场景
1. 日志分析:提取Nginx 5xx错误请求
需求:找出nginx_access.log中所有服务器错误的请求IP与URL
命令:
grep -E ' (500|502|503|504) ' /var/log/nginx/access.log | awk '{print "IP:"$1,"URL:"$7}' | sort | uniq -c
解析:(500|502)
用空格确保匹配状态码字段,uniq -c
统计重复IP。
2. 配置检查:验证sshd_config安全设置
需求:检查是否允许root直接登录
命令:
grep -Ev '^#|^$' /etc/ssh/sshd_config | grep -i 'permitrootlogin'
解析:先排除注释行和空行,-i
忽略大小写匹配。
3. 数据统计:TCP连接状态分布
命令:
ss -tun state all | grep -E 'tcp' | awk '{print $1}' | sort | uniq -c
执行效果:
10 ESTABLISHED2 LISTEN1 TIME_WAIT
4. 批量操作:修改所有.conf文件权限
命令:
shopt -s globstar && chmod 644 **/*.conf
解析:globstar递归匹配所有子目录的.conf文件,644确保读写权限合规。
六、避坑指南与学习技巧
1. 常见误区
- 通配符与正则的
*
混淆:通配符*
匹配任意字符,正则*
匹配前面字符0次或多次(如a*
匹配空、a、aa等)。 - 未转义特殊字符:正则中的
.
、$
、()
需转义(BRE),通配符中的*
、?
在引号内无需转义。 - globstar兼容性问题:CentOS 7默认Bash 4.2支持globstar,但需手动启用,脚本中建议添加检查:
if ! shopt -q globstar; then echo "globstar未启用,请升级Bash"; fi
2. 效率提升技巧
- 在线调试工具:用Regex101(https://regex101.com/) 实时验证正则表达式,支持Linux模式。
- 字符类优先用标准写法:
[[:digit:]]
比[0-9]
兼容性更好(支持非ASCII数字)。 - 避免过度使用正则:简单文件匹配用通配符,比find+正则更快(如
ls *.txt
优于find . -regex '.*\.txt'
)。
七、总结
- 通配符:聚焦“文件定位”,是Shell的内置功能,核心是
*
、?
、[]
与{}
的组合使用。 - 正则表达式:聚焦“文本处理”,依赖外部工具解析,ERE(
grep -E
)是日常运维的最优选择。 - 实战核心:先明确需求是“找文件”还是“处理文本”,再选择工具,复杂场景通过管道组合三者优势。
掌握本文内容可覆盖Linux日常运维中90%的文件与文本处理需求,建议结合实际场景反复练习,重点关注日志分析与配置管理类实战案例。