Linux基础及应用教程:文本三剑客之sed

一、实验目标

二、实验环境

三、实验内容与步骤

文件准备(创建实验环境)

本实验将同时使用自建测试文本系统自带配置文件的副本进行练习,避免误改系统关键文件。

# 1. 创建实验目录
mkdir -p ~/sed_lab
cd ~/sed_lab

# 2. 准备一个多行测试文本文件
cat > poem.txt << 'EOF'
The quick brown fox jumps over the lazy dog.
The quick brown fox likes Linux.
linux is powerful and flexible.
SED is a stream editor.
Sed can replace, delete, insert and transform text.
EOF

# 3. 准备一个带有简单配置格式的文件
cat > config.txt << 'EOF'
# Sample configuration file
HOST=localhost
PORT=8080
USER=admin
PASS=123456
LOG_LEVEL=info
EOF

# 4. 复制系统自带文本文件作为练习(只在自己的家目录操作)
# /etc/passwd 是很典型的系统用户信息文件,这里只拷贝一份出来练习
cp /etc/passwd passwd.sample

# 再准备一个日志模拟文件
cat > app.log << 'EOF'
[2025-01-01 10:00:00] INFO  Service started on port 8080
[2025-01-01 10:05:00] WARN  High memory usage detected
[2025-01-01 10:10:00] ERROR Failed to connect to database
[2025-01-01 10:15:00] INFO  Service is running
EOF

之后的所有 sed 练习命令均在 ~/sed_lab 目录中完成。

任务1:sed命令基础使用

  1. 查看文件内容:默认行为(逐行读取并输出)

    # 使用 sed 直接查看文件(等价于 cat + 过滤)
    sed '' poem.txt
    
    # 传统写法:sed -e '命令'
    sed -e '' poem.txt

    说明:空命令 '' 表示不对文本进行修改,只是原样输出。

  2. 打印指定行:p 命令与 -n 选项

    # 打印第 2 行
    sed -n '2p' poem.txt
    
    # 打印第 1 到 3 行
    sed -n '1,3p' poem.txt
    
    # 打印最后 1 行($ 表示最后一行)
    sed -n '$p' poem.txt

    -n:关闭默认输出,只输出被 p 命令选中的行。

  3. 多条命令执行:使用 -e{} 分组

    # 用 -e 指定多条命令
    sed -n -e '1p' -e '$p' poem.txt   # 打印首行和末行
    
    # 使用 {} 在地址范围内执行多条命令
    sed -n '2,4{=;p}' poem.txt        # 打印 2-4 行以及行号(=)
  4. 显示行号:= 命令

    # 打印所有行的行号和内容
    sed -n '=;p' poem.txt

任务2:文本替换与正则

sed 中,最常用的命令之一就是替换命令 s/模式/替换/标志

# 1. 最基本的替换:只替换每行的第一个匹配
sed 's/Linux/Unix/' poem.txt

# 2. 全局替换:行内所有匹配都替换(加 g 标志)
sed 's/linux/Linux/g' poem.txt

# 注意:sed 默认区分大小写,Linux 与 linux 不一样
# 可以先统一大小写再替换,或用正则匹配多种写法

使用正则表达式进行模式匹配:

# 3. 使用正则匹配单词边界:只替换单词 'Sed'(不误伤单词内部)
sed 's/\<Sed\>/sed/g' poem.txt

# 4. 替换包含特殊字符的内容:使用其他分隔符,如 #
sed 's#8080#9090#g' app.log

# 5. 使用 & 引用匹配到的内容
# 把所有包含 Linux 的行中 'Linux' 替换为 '[Linux系统]'
sed 's/Linux/[&系统]/g' poem.txt

# 6. 使用括号分组和 \1、\2 反向引用(GNU sed 要用 -r 或 -E)
sed -r 's/(HOST)=(.+)/\1=192.168.0.1/' config.txt

# 7. 忽略大小写匹配(GNU sed 支持 I 标志)
sed 's/linux/Linux/Ig' poem.txt

只在匹配某种模式的行中进行替换:

# 只在包含 'INFO' 的日志行中把 'Service' 改成 'Server'
sed '/INFO/s/Service/Server/' app.log

# 只在行号 2-4 中替换 'quick' 为 'slow'
sed '2,4s/quick/slow/' poem.txt

任务3:行选取、删除与插入

删除行:d 命令

# 1. 删除第 1 行
sed '1d' poem.txt

# 2. 删除第 2-3 行
sed '2,3d' poem.txt

# 3. 删除所有包含 ERROR 的日志行
sed '/ERROR/d' app.log

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

插入与追加:i(在前插入)、a(在后追加)

# 1. 在第 1 行前插入一行标题(注意末尾不用写 \)
sed '1i This is a poem about Linux.' poem.txt

# 2. 在文件末尾追加一行($ 表示最后一行)
sed '$a This is the end of the poem.' poem.txt

# 3. 在包含 'SED' 的行前插入注释
sed '/SED/i # SED related line below' poem.txt

替换整行内容:c 命令

# 将第 2 行整行替换为固定文本
sed '2c <This line has been replaced by sed>' poem.txt

# 将包含 'WARN' 的日志行全部替换为统一提示
sed '/WARN/c [WARN] please pay attention to system performance.' app.log

多行范围操作:地址范围 + 命令

# 对从 'HOST' 开始到 'USER' 所在行的范围内,添加注释前缀 #
sed '/HOST/,/USER/s/^/# /' config.txt

# 删除从 'WARN' 到 'ERROR' 之间(含)所有日志行
sed '/WARN/,/ERROR/d' app.log

任务4:结合管道与系统文本

本任务通过 passwd.sample 等系统文本的副本,模拟运维场景。

# 1. 使用管道只提取系统用户名前两列
# /etc/passwd 每行格式一般为:用户名:密码占位:UID:GID:注释:家目录:Shell
cat passwd.sample | sed 's/:.*//'

# 2. 显示 UID >= 1000 的普通用户(结合 awk 或 grep)
# 简单示例:先用 grep,再用 sed 清理字段
grep ':/home/' passwd.sample | sed 's/:.*//'

# 3. 配合行号查看特定配置行
nl -ba config.txt | sed -n '1,5p'

# 4. 在管道中对日志进行快速过滤与替换
cat app.log | sed '/INFO/d' | sed 's/ERROR/FATAL/g'

sed 与其他命令组合:

# 5. 实时查看某个日志并用 sed 高亮(简单方法:添加标签)
tail -f app.log | sed 's/ERROR/[ERROR]/'

# 6. 从 ps 输出中用 sed 提取特定字段(示例)
ps aux | sed -n '1p; /sshd/p'

任务5:配置文件批量修改实战

本任务模拟实际运维场景,对配置文件进行批量修改,并学习 -i 选项(原地修改)和备份。

一、在不修改原文件的前提下,预览修改效果

cd ~/sed_lab

# 1. 将 config.txt 中的 PORT 改为 9090(仅预览)
sed 's/^PORT=8080/PORT=9090/' config.txt

# 2. 将 LOG_LEVEL 从 info 改为 debug(仅预览)
sed 's/^LOG_LEVEL=info/LOG_LEVEL=debug/' config.txt

二、使用 -i 选项直接修改文件(务必注意备份)

# 1. 先查看原文件内容
cat config.txt

# 2. 修改前做好备份(推荐)
cp config.txt config.txt.bak

# 3. 使用 sed -i 原地修改(部分系统要求 -i 后必须直接跟备份后缀)
# 方式一:手动备份 + 简单 -i
sed -i 's/^PORT=8080/PORT=9090/' config.txt

# 方式二:让 sed 自动生成备份文件
sed -i.bak 's/^LOG_LEVEL=info/LOG_LEVEL=debug/' config.txt

# 4. 查看修改结果
cat config.txt
ls config.txt*

三、综合实战:统一修改密码策略、注释无用配置

# 假设我们决定不再在配置文件中存储明文密码,
# 用 sed 将 PASS 字段整行注释掉,并添加说明

cp config.txt config.txt.secure.bak

# 1. 注释掉 PASS 行
sed -i 's/^PASS/#PASS/' config.txt

# 2. 在 PASS 行后追加一行说明
sed -i '/^#PASS/a # NOTE: password is now managed by an external secret manager.' config.txt

# 3. 检查最终结果
cat config.txt

四、实验报告要求

五、常见问题解答

回到首页 回到主页