在Linux中,正则表达式是文本处理的重要工具,结合 grepsedawk,可以高效地进行文本过滤、替换、统计等多种操作。

正则规则

正则表达式 描述 示例 Basic RegEx Extended RegEx Python RegEx Perl RegEx
\ 转义符,将特殊字符转义为其字面意义 a\.b 匹配 “a.b”,不匹配 “ajb” 支持 支持 支持 支持
^ 匹配行首(或字符串开头,如在 awk 中) ^tux 匹配以 “tux” 开头的行 支持 支持 支持 支持
$ 匹配行尾(或字符串结尾,如在 awk 中) tux$ 匹配以 “tux” 结尾的行 支持 支持 支持 支持
. 匹配除换行符(\n)外的任意单个字符 ab. 匹配 “abc” 或 “abd”,不匹配 “abcd” 支持 支持 支持 支持
[ ] 匹配括号内包含的任意一个字符 coo[kl] 匹配 “cook” 或 “cool” 支持 支持 支持 支持
[^ ] 匹配不在括号内的任意一个字符 123[45] 不匹配 “1234” 或 “1235”,匹配 “1236” 支持 支持 支持 支持
[-] 匹配指定字符范围内的任意一个字符 [0-9] 匹配任意一个数字 支持 支持 支持 支持
? 匹配前面的项 0 次或 1 次 colou?r 匹配 “color” 或 “colour” 不支持 支持 支持 支持
+ 匹配前面的项 1 次或多次 sa-6+ 匹配 “sa-6” 或 “sa-666” 不支持 支持 支持 支持
* 匹配前面的项 0 次或多次 co*l 匹配 “cl”、”col”、”cool” 支持 支持 支持 支持
( ) 将表达式分组,创建一个子串或用于反向引用 ma(tri)?x 匹配 “max” 或 “matrix” 不支持 支持 支持 支持
{n} 匹配前面的项恰好 n 次 [0-9]{3} 匹配任意三位数 不支持 支持 支持 支持
{n,} 匹配前面的项至少 n 次 [0-9]{2,} 匹配任意两位数或更多位数 不支持 支持 支持 支持
{n,m} 匹配前面的项至少 n 次,至多 m 次 [0-9]{2,5} 匹配两位数到五位数 不支持 支持 支持 支持
| 交替匹配,匹配 | 左边或右边的项 ab(c|d) 匹配 “abc” 或 “abd” 不支持 支持 支持 支持

grep命令

  • 基本语法
    1
    grep [选项] "模式" 文件名

常用示例

  • 基础文本搜索
    1
    2
    3
    4
    5
    # 在文件中查找包含特定字符串的行
    grep "hello" file.txt

    # 结合正则表达式匹配(需添加-E参数)
    ip a | grep -E "ens33$"
  • 递归搜索
    1
    2
    3
    4
    5
    6
    7
    8
    # 递归查找/etc目录下包含'ens33'的文件
    grep -r 'ens33' /etc

    # 忽略大小写递归搜索
    grep -ir 'ens33' /etc

    # 忽略大小写并显示行号
    grep -irn 'ens33' /etc
  • 正则表达式应用
    1
    2
    3
    4
    5
    # 匹配以ens33结尾的行
    grep -Er 'ens33$' /etc

    # 排除空行和注释行(以#开头)
    grep -Ev "^$|^#" file

sed命令

  • 基本语法
    1
    sed [选项] '命令' 文件名

常用操作示例

  • 文本替换
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 全局替换字符串
    sed 's/old-string/new-string/g' input.txt > output.txt

    # 替换文件中的Jack为Mark(仅每行第一个)
    sed 's/Jack/Mark/' sed-examp.txt

    # 全局替换Jack为Mark
    sed 's/Jack/Mark/g' sed-examp.txt

    # 替换第2-3行的hello为Hey
    sed '2,3s/hello/Hey/g' sed-examp.txt

    # 仅替换包含Pony的行
    sed '/Pony/s/hello/Hi/g' sed-examp.txt

    # 替换不包含Pony的行
    sed '/Pony/!s/hello/Hi/g' sed-examp.txt
  • 删除操作
    1
    2
    3
    4
    5
    6
    7
    8
    # 删除第2-3行
    sed '2,3d' sed-examp.txt

    # 删除包含Pony的行
    sed '/Pony/d' sed-examp.txt

    # 删除空白行
    sed '/^$/d' sed-examp.txt
  • 插入和追加
    1
    2
    3
    4
    5
    6
    7
    8
    # 在第一行前插入内容
    sed '1i\Welcome' sed-examp.txt

    # 在第一行后追加内容
    sed '1a\Welcome' sed-examp.txt

    # 在匹配行后追加内容
    sed '/Pony/aWelcome' sed-examp.txt
  • 高级用法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 打印匹配行(类似grep)
    sed -n '/Pony/p' sed-examp.txt

    # 多条件操作
    sed -e '/^$/d' -e '/Pony/d' sed-examp.txt
    # 或
    sed '/^$/d; /Pony/d' sed-examp.txt

    # 直接修改源文件
    sed -i -e '/^$/d' -e '/Pony/d' sed-examp.txt

    # 修改源文件并备份
    sed -i.bak '/^$/d; /Pony/d' sed-examp.txt
  • 高级文本处理
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 交换两列内容
    echo "Alice 30" | sed 's/\(.*\) \(.*\)/\2 \1/'

    # 日志处理:提取ERROR信息并格式化
    sed -n '/ERROR/s/\(202[0-9]-[0-9][0-9]-[0-9][0-9]\) .*ERROR\] \(.*\)/\1 \2/p' log.txt
    # 简化写法
    sed -n -r '/ERROR/s/(202[0-9]-[0-9][0-9]-[0-9]{2}) .*ERROR] (.*)/\1 \2/p' log.txt

    # 日期格式转换
    sed -n -r 's/([0-9]{4})-([0-9]{2})-([0-9]{2})(.*)/\3\/\2\/\1\4/p' log.txt

awk命令

  • 基本语法
    1
    2
    3
    4
    5
    # 格式1
    awk [选项] '[条件]{指令}' 文件

    # 格式2
    前置指令 | awk [选项] '[条件]{指令}'
  • 内置变量
    1
    2
    3
    4
    5
    6
    7
    $0:文本当前行的全部内容

    $1、$2、$3...:文本的第1、2、3...列

    NR:文件当前行的行号

    NF:文件当前行的列数

常用示例

  • 基础文本处理
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    # 准备测试数据
    head /etc/passwd > user

    # 打印以bin开头的行
    awk '/^bin/{print}' user

    # 指定分隔符并打印特定列
    awk -F: '/^bin/{print $6}' user

    # 打印多列信息
    awk -F: '/^bin/{print $6,NR,NF}' user

    # 打印最后一列
    awk -F: '/^bin/{print $6,NR,$NF}' user

    # 打印以nologin结尾的用户名
    awk -F: '/nologin$/{print $1}' user

    # 多分隔符处理
    awk -F[:/] '/nologin$/{print $1,$10}' user

    # 格式化输出
    awk -F: '{print "用户是: "$1" 使用的shell是: "$7}' user
  • 结构化输出
    1
    2
    # BEGIN、主体处理、END结合使用
    awk -F: 'BEGIN{print "User\tUID\tHome"}{print $1"\t"$3"\t"$6}END{print "Total "NR" lines."}' /etc/passwd
  • 条件过滤
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 正则表达式条件
    awk -F: '$6~/root/{print}' user # 第六列包含root
    awk -F: '$6!~/root/{print}' user # 第六列不包含root

    # 数值比较
    awk -F: '$3<3{print}' user # UID小于3
    awk -F: '$3>=3{print}' user # UID大于等于3
    awk -F: '$3!=3{print}' user # UID不等于3

    # 多条件组合
    awk -F: 'NR>3&&$3>5{print}' user # 行号>3且UID>5
    awk -F: '$7~/bash/&&$3<500{print}' user # shell包含bash且UID<500
    awk -F: '$7~/bash/||NR<=3' user # shell包含bash或行号<=3
    awk -F: 'NR%2==0{print NR,$0}' user # 偶数行
  • 数组应用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # 统计单词出现次数
    echo "apple orange banana apple orange" | awk '
    {
    for(i=1;i<=NF;i++) count[$i]++
    }
    END {
    for(word in count) print word, count[word]
    }'

    # 统计IP访问次数(Web日志分析)
    # 安装并启动Apache服务
    yum install -y httpd
    systemctl stop firewalld
    setenforce 0
    systemctl start httpd

    # 生成访问日志
    curl 127.0.0.1
    curl 127.0.0.1
    curl 127.0.0.1

    # 统计IP访问次数
    awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' /var/log/httpd/access_log

    # 统计页面访问次数
    awk -F\/ '{pages[$4]++}END{for(p in pages){print p,pages[p]}}' /var/log/httpd/access_log

总结

  • grep:专注于文本搜索和匹配

  • sed:擅长流编辑和文本转换

  • awk:具备完整的编程能力,适合复杂文本处理和数据提取