从入门到精通Shell正则表达式实战

Written by

in

文章目录
  • 使用 grep -E、sed -E 或 awk 时,元字符无需转义,功能更强大。
  • 为了兼容不同字符集(如中文),Shell 提供了 POSIX 字符类,需用 [[]] 包裹: 字符类 说明 等价于(ASCII) [:alnum:] 字母和数字 [a-zA-Z0-9] [:alpha:] 字母 [a-zA-Z] [:digit:] 数字 [0-9] [:lower:] 小写字母 [a-z] [:upper:] 大写字母 [A-Z] [:space:] 空白字符(空格、制表符等) [ tnrfv] [:punct:] 标点符号 [!"#$%&'()*+,-./:;<=>?@[\]^_{ }~]` 示例:匹配包含数字的行 grep ‘[[:digit:]]’ file.txt
  • 转义问题: BRE 中 +、?、|、()、{} 需转义,ERE 中无需转义。 在 Shell 脚本中使用正则时,注意单引号 ' 和双引号 " 的区别:单引号内的元字符不会被 Shell 解析,推荐使用单引号包裹正则。 贪婪匹配 vs 非贪婪匹配: 默认是贪婪匹配(尽可能多匹配),如 a.*b 匹配 aabab 中的整个字符串。 非贪婪匹配需用 PCRE(grep -P),如 a.*?b 匹配 aab。 字符集问题: 处理中文时,确保终端和文件编码一致(如 UTF-8),推荐使用 POSIX 字符类(如 [:alpha:] 匹配中文字母)。 到此这篇关于Shell正则表达式实战:从入门到精通的文章就介绍到这了,更多相关Shell正则表达式内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: shell编程入门之正则表达式实例代码 shell正则表达式、grep命令和sed命令举例详解 shell脚本中的正则表达式详解 Shell中正则表达式及sed和awk常见问题 shell高级学习之正则表达式 shell脚本之正则表达式、grep、sed、awk 详解Linux–shell脚本之正则表达式 Linux Shell脚本的编程之正则表达式
  • 目录
    • 一、正则表达式概述与 Shell 工具支持
      • 1. 正则表达式的类型
      • 2. 核心工具速览
    • 二、基本正则表达式(BRE)
      • 1. 基础元字符
      • 2. 范围匹配与重复(BRE 需转义)
    • 三、扩展正则表达式(ERE)
      • 1. 扩展元字符
    • 四、POSIX 字符类
      • 五、实际工具应用(超详细示例)
        • 1.grep:文本查找
          • 基础用法
          • 进阶:结合扩展正则
        • 2.sed:文本替换与编辑
          • 基础替换
          • 进阶:结合正则与分组
        • 3.awk:文本处理与数据分析
          • 基础用法
          • 进阶:结合正则
      • 六、常见实用正则示例
        • 1. 匹配手机号(中国大陆)
          • 2. 匹配 IP 地址(简化版,不验证合法性)
            • 3. 匹配日期(YYYY-MM-DD)
              • 4. 提取 HTML 中的链接(简化版)
              • 七、注意事项与避坑指南

                正则表达式(Regular Expression, Regex)是 Shell 编程中处理文本的核心工具,配合 grepsedawk 等工具可实现强大的文本查找、替换、提取功能。本教程从基础到进阶,结合大量可直接运行的示例,帮你彻底掌握 Shell 正则表达式。

                Shell 中主要使用三种正则规范,不同工具支持的类型不同:

                类型 说明 支持工具
                基本正则(BRE) 基础元字符,部分元字符需转义 grep(默认)、sed(默认)
                扩展正则(ERE) 更多元字符,无需额外转义 grep -Esed -Eawk
                Perl 兼容正则(PCRE) 功能最强,支持非贪婪匹配等高级特性 grep -P

                • grep:文本查找(Global Regular Expression Print)
                • sed:文本替换、编辑(Stream Editor)
                • awk:文本处理、数据分析(Aho-Weinberger-Kernighan)

                元字符 功能说明 示例 示例解释
                ^ 匹配行首 grep '^root' /etc/passwd 匹配以root开头的行
                $ 匹配行尾 grep 'bash$' /etc/passwd 匹配以bash结尾的行
                . 匹配任意单个字符(除换行) grep 'r..t' /etc/passwd 匹配rt之间有 2 个任意字符的行(如rootrbtx
                * 匹配前一个字符 0 次或多次 grep 'ro*t' /etc/passwd 匹配rtrotrootrooot
                [] 匹配括号内任意单个字符 grep 'r[ao]t' file.txt 匹配ratrot
                [^] 匹配不在括号内的任意字符 grep 'r[^ao]t' file.txt 匹配rbtrct等,但不匹配ratrot
                转义元字符,使其失去特殊含义 grep 'www.example.com' file.txt 匹配字面量www.example.com.被转义)

                在 BRE 中,以下元字符必须加 转义才生效:

                元字符(转义后) 功能说明 示例
                {n} 匹配前一个字符恰好n grep 'ro{2}t' /etc/passwd 匹配rooto恰好 2 次)
                {n,} 匹配前一个字符至少n grep 'ro{2,}t' file.txt 匹配rootrooot
                {n,m} 匹配前一个字符nm grep 'ro{1,3}t' file.txt 匹配rotrootrooot

                使用 grep -Esed -Eawk 时,元字符无需转义,功能更强大。

                元字符 功能说明 示例(用grep -E)
                + 匹配前一个字符 1 次或多次 grep -E 'ro+t' file.txt 匹配rotrootrooot(不匹配rt
                ? 匹配前一个字符 0 次或 1 次 grep -E 'ro?t' file.txt 匹配rtrot
                ` ` 或逻辑,匹配左右任意一个 `grep -E 'root admin' /etc/passwd` 匹配包含rootadmin的行
                () 分组,将多个字符视为整体 grep -E '(root)+' file.txt 匹配rootrootroot
                {n} 匹配前一个字符恰好n次(无需转义) grep -E 'ro{2}t' file.txt 匹配root
                {n,} 匹配前一个字符至少n grep -E 'ro{2,}t' file.txt 匹配rootrooot
                {n,m} 匹配前一个字符nm grep -E 'ro{1,3}t' file.txt 匹配rotrootrooot

                为了兼容不同字符集(如中文),Shell 提供了 POSIX 字符类,需用 [[]] 包裹:

                字符类 说明 等价于(ASCII)
                [:alnum:] 字母和数字 [a-zA-Z0-9]
                [:alpha:] 字母 [a-zA-Z]
                [:digit:] 数字 [0-9]
                [:lower:] 小写字母 [a-z]
                [:upper:] 大写字母 [A-Z]
                [:space:] 空白字符(空格、制表符等) [ tnrfv]
                [:punct:] 标点符号 [!"#$%&'()*+,-./:;<=>?@[\]^_{ }~]`

                示例:匹配包含数字的行

                grep '[[:digit:]]' file.txt

                # 查找包含"error"的行(忽略大小写)
                grep -i 'error' log.txt
                # 查找不包含"debug"的行
                grep -v 'debug' log.txt
                # 显示匹配行的行号
                grep -n 'root' /etc/passwd
                # 递归查找当前目录下所有文件中的"TODO"
                grep -r 'TODO' .

                # 查找以"202"开头的年份(如2020、2021...2029)
                grep -E '^202[0-9]' dates.txt
                # 查找邮箱(简化版)
                grep -E '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}' emails.txt

                sed 默认使用 BRE,加 -E 启用 ERE。

                # 将文件中所有"apple"替换为"orange"(直接修改文件:加-i)
                sed 's/apple/orange/g' file.txt > new_file.txt
                sed -i 's/apple/orange/g' file.txt  # 直接修改原文件
                # 只替换第2次出现的"apple"
                sed 's/apple/orange/2' file.txt

                # 将"root:x:0:0:root:/root:/bin/bash"改为"User: root, Shell: /bin/bash"
                # 分组1匹配root,2匹配/bin/bash
                sed -E 's/^([a-z]+):.*:([^:]+)$/User: 1, Shell: 2/' /etc/passwd
                # 删除空行
                sed '/^$/d' file.txt
                # 删除以#开头的注释行
                sed '/^#/d' file.txt

                awk 默认使用 ERE,功能极其强大。

                # 打印/etc/passwd的第1列(用户名)和第7列(Shell)
                awk -F: '{print $1, $7}' /etc/passwd
                # 打印第3列(UID)大于1000的行
                awk -F: '$3 > 1000' /etc/passwd

                # 打印以"r"开头的用户名及其Shell
                awk -F: '$1 ~ /^r/ {print $1, $7}' /etc/passwd
                # 统计日志中"error"出现的次数
                awk '/error/ {count++} END {print "Error count:", count}' log.txt
                # 提取IP地址(简化版)
                awk '/([0-9]{1,3}.){3}[0-9]{1,3}/ {print $0}' access.log

                grep -E '^1[3-9][0-9]{9}$' phones.txt

                grep -E '([0-9]{1,3}.){3}[0-9]{1,3}' ips.txt

                grep -E '^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$' dates.txt

                grep -Eo 'href="[^" rel="external nofollow" ]+"' index.html | sed -E 's/href="([^" rel="external nofollow" ]+)"/1/'

                • 转义问题
                  • BRE 中 +?|(){} 需转义,ERE 中无需转义。
                  • 在 Shell 脚本中使用正则时,注意单引号 ' 和双引号 " 的区别:单引号内的元字符不会被 Shell 解析,推荐使用单引号包裹正则。
                • 贪婪匹配 vs 非贪婪匹配
                  • 默认是贪婪匹配(尽可能多匹配),如 a.*b 匹配 aabab 中的整个字符串。
                  • 非贪婪匹配需用 PCRE(grep -P),如 a.*?b 匹配 aab
                • 字符集问题
                  • 处理中文时,确保终端和文件编码一致(如 UTF-8),推荐使用 POSIX 字符类(如 [:alpha:] 匹配中文字母)。

                到此这篇关于Shell正则表达式实战:从入门到精通的文章就介绍到这了,更多相关Shell正则表达式内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

                您可能感兴趣的文章:

                • shell编程入门之正则表达式实例代码
                • shell正则表达式、grep命令和sed命令举例详解
                • shell脚本中的正则表达式详解
                • Shell中正则表达式及sed和awk常见问题
                • shell高级学习之正则表达式
                • shell脚本之正则表达式、grep、sed、awk
                • 详解Linux–shell脚本之正则表达式
                • Linux Shell脚本的编程之正则表达式

                站内搜索