飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • 基础入门

    • Linux 命令概述与环境准备
    • 文件与目录操作(上):ls、cd、pwd
    • 文件与目录操作(下):cat、touch、mkdir、rm、cp、mv
    • 获取帮助与基础工具:man、help、clear、exit、sudo
  • 文件权限

    • 文件权限管理:chmod、chown
  • 系统与监控

    • 进程管理与系统监控:ps、top、kill、df、du、free
    • 用户与环境:whoami、id、env、echo、history
  • 网络命令

    • 网络诊断(上):ping、curl、wget
    • 网络诊断(下):netstat、ss、ip
    • 网络抓包与高级工具:traceroute、tcpdump、nc
    • DNS 与防火墙:nslookup、dig、iptables
  • 文本处理

    • 文本搜索:grep
    • 文本处理(上):awk
    • 文本处理(下):sed
    • 文本排序与统计:sort、uniq、wc
    • 文件查看与查找:head、tail、cut、find
    • 归档压缩与管道组合:tar、gzip、xargs
  • 开发工具

    • 开发工具链(上):gcc、make
    • 开发工具链(下):gdb、time
    • 版本控制:git
    • 远程操作:ssh、scp
    • 编辑器:vim、nano
  • Shell 编程

    • Shell 编程基础(上):变量、管道、重定向
    • Shell 编程基础(下):条件、循环、函数
  • 综合实战

    • 综合实战:日志分析

文本处理(下):sed

sed 核心定位

sed(Stream Editor)是流编辑器,对文本进行非交互式的批量修改。它逐行读取输入,应用编辑命令,输出结果。

与 vim 的区别:

  • vim:交互式编辑器,打开文件,手动编辑,保存退出
  • sed:非交互式,适合脚本中批量处理,不修改原文件(除非 -i)

基础语法

sed 'command' file          # 对 file 执行 command,输出到屏幕
sed -i 'command' file       # 直接修改文件(in-place)
sed -e 'cmd1' -e 'cmd2' file # 执行多个命令

最常用:替换(s 命令)

# 基本替换:每行第一个匹配
sed 's/old/new/' file.txt

# 全局替换(g = global):每行所有匹配
sed 's/old/new/g' file.txt

# 替换第 2 个匹配
sed 's/old/new/2' file.txt

# 替换第 2 个及之后的所有匹配
sed 's/old/new/2g' file.txt

# 使用其他分隔符(避免转义 /)
sed 's#/usr/local#/opt#g' file.txt    # 用 # 代替 /
sed 's|/usr/local|/opt|g' file.txt    # 用 | 代替 /

# 替换并直接修改文件(-i)
sed -i 's/old/new/g' file.txt

# 替换前备份(-i.bak)
sed -i.bak 's/old/new/g' file.txt     # 原文件备份为 file.txt.bak

替换中的特殊符号

符号含义示例
&代表匹配的整个字符串sed 's/hello/[&]/' → [hello]
\1 \2代表第 n 个捕获组sed 's/\(hello\) \(world\)/\2 \1/'
# 给每行加引号
sed 's/.*/"&"/' file.txt

# 交换两个单词的位置
sed 's/\(word1\) \(word2\)/\2 \1/' file.txt

# 给匹配内容加标记
sed 's/error/[ERROR: &]/g' log.txt

删除行(d 命令)

# 删除第 3 行
sed '3d' file.txt

# 删除第 2 到 5 行
sed '2,5d' file.txt

# 删除包含 "test" 的行
sed '/test/d' file.txt

# 删除以 # 开头的行(注释行)
sed '/^#/d' file.txt

# 删除空行
sed '/^$/d' file.txt

# 删除第 1 行(常用于去掉 CSV 标题)
sed '1d' file.csv

打印行(p 命令)

# 打印第 3 行(-n 抑制默认输出,只打印匹配行)
sed -n '3p' file.txt

# 打印第 2 到 5 行
sed -n '2,5p' file.txt

# 打印包含 "error" 的行
sed -n '/error/p' file.txt

# 打印最后一行($ 表示最后一行)
sed -n '$p' file.txt

# 打印奇数行(步长为 2)
sed -n '1~2p' file.txt

# 打印偶数行
sed -n '2~2p' file.txt

插入和追加(i 和 a 命令)

# 在第 3 行前插入(i = insert)
sed '3i\This is inserted before line 3' file.txt

# 在第 3 行后追加(a = append)
sed '3a\This is appended after line 3' file.txt

# 在包含 "hello" 的行前插入
sed '/hello/i\New line before hello' file.txt

# 在文件开头插入一行
sed '1i\# Header comment' file.txt

# 在文件末尾追加一行
sed '$a\# Footer comment' file.txt

多命令组合

# 使用 -e 连接多个命令
sed -e 's/foo/bar/g' -e 's/hello/hi/g' file.txt

# 使用分号分隔
sed 's/foo/bar/g; s/hello/hi/g' file.txt

# 使用脚本文件(-f)
cat > script.sed
s/foo/bar/g
/hello/d
1i\# Header
# Ctrl+D

sed -f script.sed file.txt

实战场景

场景 1:批量修改配置文件

# 修改 IP 地址
sed -i 's/192.168.1.100/192.168.1.200/g' config.txt

# 修改端口号
sed -i 's/port=8080/port=9090/' config.txt

# 取消注释(去掉行首的 #)
sed -i 's/^#\(listen\)/\1/' config.txt

# 添加注释(在行首加 #)
sed -i 's/^listen/#listen/' config.txt

场景 2:格式化输出

# 给每行加行号
sed = file.txt | sed 'N; s/\n/ /'

# 删除行尾空格
sed 's/[[:space:]]*$//' file.txt

# 将多个空行合并为一个
sed '/^$/N; /^\n$/D' file.txt

# 在文件末尾添加空行(如果原来没有)
sed -e '$a\' file.txt

场景 3:结合管道使用

# 查看进程,去掉 grep 自身
ps aux | grep nginx | sed '/grep/d'

# 查看 IP 地址,只显示 IP 行
ip addr | sed -n '/inet /p'

# 提取版本号
cat version.txt | sed 's/version //'

本篇小结

  • sed 是流编辑器,逐行处理,适合批量修改和脚本自动化
  • s/old/new/g:替换命令,g 全局替换,& 代表匹配内容,\1 代表捕获组
  • d:删除行,3d 删除第 3 行,/pattern/d 删除匹配行
  • p:打印行,配合 -n 只输出匹配行,$p 打印最后一行
  • i:行前插入,a:行后追加
  • -i:直接修改文件,-i.bak 修改前备份
  • -e:执行多个命令,-f:从脚本文件读取命令

动手实践

  1. 创建测试文件并替换:

    cat > test.txt
    hello world
    hello linux
    hello sed
    # Ctrl+D
    
    sed 's/hello/hi/' test.txt        # 每行第一个
    sed 's/hello/hi/g' test.txt       # 全局
    sed -i.bak 's/hello/hi/g' test.txt # 修改并备份
    cat test.txt
    cat test.txt.bak
    
  2. 删除练习:

    sed '2d' test.txt                 # 删除第 2 行
    sed '/linux/d' test.txt           # 删除包含 linux 的行
    sed '/^$/d' test.txt              # 删除空行
    
  3. 打印练习:

    sed -n '2p' test.txt              # 打印第 2 行
    sed -n '1,2p' test.txt            # 打印 1-2 行
    sed -n '$p' test.txt              # 打印最后一行
    
  4. 配置文件修改:

    cat > config.txt
    host=localhost
    port=8080
    debug=true
    # Ctrl+D
    
    sed -i 's/localhost/127.0.0.1/' config.txt
    sed -i 's/port=8080/port=9090/' config.txt
    sed -i 's/true/false/' config.txt
    cat config.txt
    
  5. 结合管道:

    ps aux | sed -n '/bash/p' | sed '/grep/d'
    
  6. 思考:sed 's/old/new/' 和 sed 's/old/new/g' 有什么区别?如果一行中有 3 个 "old",前者会替换几个?后者会替换几个?

上一页
文本处理(上):awk
下一页
文本排序与统计:sort、uniq、wc