sed 核心知识点
第一步:准备示例文本文件
请将以下内容保存为一个名为 data.txt 的文本文件。这个文件模拟了一些常见的日志或配置文件片段,包含了我们需要练习的各种元素。
# /etc/config/app_settings.conf
# Application Configuration File
[General]
AppName=MyApp
Version=1.0.3
LogLevel=INFO
DebugMode=false
[Database]
DB_Host=db.example.com
DB_Port=3306
DB_User=app_user
DB_Pass=S3cr3tP@ssw0rd! # Default password, please change!
DB_Name=production_db
[Server]
ListenAddress=0.0.0.0
ListenPort=8080
MaxConnections=1000
UseSSL=true
# User List Section - TODO: Move to database
User1=alice ; admin
User2=bob ; user
User3=charlie ; user # Temporary account
# Log entries simulation
[2023-10-27 10:00:01] INFO: Application MyApp version 1.0.3 started.
[2023-10-27 10:00:05] DEBUG: Connection pool initialized. (DebugMode is off)
[2023-10-27 10:01:15] WARN: MaxConnections nearing limit (950/1000).
[2023-10-27 10:02:00] ERROR: Failed to connect to secondary service on 192.168.1.254:9999
[2023-10-27 10:02:10] INFO: User 'alice' logged in.
[2023-10-27 10:05:30] INFO: Configuration file reloaded.
[2023-10-27 10:10:00] ERROR: Database query failed for user 'bob'. SQLState: HY000
第二步:学习 sed 核心功能及典型任务
现在,我们来逐一学习 sed 的核心功能。sed (Stream EDitor) 是一个极其强大的文本处理工具,尤其擅长基于行进行编辑。掌握它的核心功能对于运维工作非常有帮助。
基础语法: sed [选项] '命令' [输入文件...]
重要提示:
- 默认情况下,
sed不会修改原始文件,而是将处理结果输出到标准输出 (stdout)。 - 使用 
-i选项可以直接修改文件(请极其小心使用,建议先不带-i测试,或者使用-i.bak创建备份)。 - 单引号 
' '用于包围sed命令,防止 Shell 解释其中的特殊字符。 
场景 1: 打印特定行 (行寻址与打印 p)
sed 默认会打印处理后的每一行。-n 选项可以禁止默认打印,常与 p (print) 命令结合使用,只打印我们明确指定的行。
- 
任务: 打印文件的第 3 行。
- 命令:
sed -n '3p' data.txt - 解释: 
-n禁止默认输出,3是行地址,p是打印命令。只打印第 3 行。 
 - 命令:
 - 
任务: 打印文件的第 5 行到第 8 行。
- 命令:
sed -n '5,8p' data.txt - 解释: 
5,8是行地址范围,打印这个范围内的行。 
 - 命令:
 - 
任务: 打印所有包含 "ERROR" 的行。
- 命令:
sed -n '/ERROR/p' data.txt - 解释: 
/ERROR/是一个正则表达式地址,匹配包含 "ERROR" 的行,p打印匹配行。 
 - 命令:
 - 
任务: 打印所有以 "#" 开头的行(注释行)。
- 命令:
sed -n '/^#/p' data.txt - 解释: 
/^#/正则表达式地址,^表示行首,#是要匹配的字符。 
 - 命令:
 - 
任务: 打印从包含 "[Database]" 的行开始,到第一个空行之间的所有行。
- 命令:
sed -n '/\[Database]/,/^$/p' data.txt - 解释: 
/\[Database]/,/^$/是一个由两个正则表达式定义的地址范围。[需要转义\[。/^$/匹配空行。 
 - 命令:
 
场景 2: 删除特定行 (行寻址与删除 d)
d (delete) 命令用于删除匹配的行。注意,默认情况下 sed 只是不打印这些行到标准输出,原始文件不变。
- 
任务: 删除所有空行。
- 命令:
sed '/^$/d' data.txt - 解释: 
/^$/匹配空行,d删除匹配的行。 
 - 命令:
 - 
任务: 删除所有注释行(以 "#" 开头)。
- 命令:
sed '/^#/d' data.txt - 解释: 
/^#/匹配注释行,d删除。 
 - 命令:
 - 
任务: 删除第 10 行。
- 命令:
sed '10d' data.txt - 解释: 
10是行地址,d删除第 10 行。 
 - 命令:
 - 
任务: 删除从第 1 行到第 3 行。
- 命令:
sed '1,3d' data.txt - 解释: 
1,3是行地址范围,d删除这个范围内的行。 
 - 命令:
 - 
任务: 删除所有包含 "DEBUG" 的行。
- 命令:
sed '/DEBUG/d' data.txt - 解释: 
/DEBUG/匹配包含 "DEBUG" 的行,d删除。 
 - 命令:
 
场景 3: 替换文本 (替换 s)
这是 sed 最常用、最强大的功能。s (substitute) 命令用于查找和替换。
基本语法: s/查找模式/替换字符串/[标志]
常用标志:
g: 全局替换 (Global),替换行内所有匹配项,而不仅仅是第一个。i: 忽略大小写 (Ignore case),(GNU sed 特有)。
- 
任务: 将每行中第一次出现的 "INFO" 替换为 "Information"。
- 命令:
sed 's/INFO/Information/' data.txt - 解释: 
s表示替换。/INFO/是查找模式。/Information/是替换字符串。默认只替换每行第一个匹配项。 
 - 命令:
 - 
任务: 将文件中所有的 "user" (小写) 替换为 "account"。
- 命令:
sed 's/user/account/g' data.txt - 解释: 
g标志表示全局替换,替换行内所有出现的 "user"。 
 - 命令:
 - 
任务: 将数据库密码那一行 (
DB_Pass=...) 中的密码替换为 "[REDACTED]"。- 命令:
sed '/^DB_Pass=/ s/=.*/=[REDACTED]/' data.txt - 解释: 
/^DB_Pass=/是地址,只在匹配此模式的行上执行后面的s命令。s/=.*/=[REDACTED]/查找第一个=及其之后的所有内容 (.*),并替换为=[REDACTED]。 
 - 命令:
 - 
任务: 更改数据库主机名
db.example.com为prod-db-replica.internal。- 命令:
sed 's/db\.example\.com/prod-db-replica.internal/' data.txt - 解释: 在查找模式中,
.是正则表达式元字符(匹配任意单个字符),需要用\转义 (\.) 来匹配字面上的点。 
 - 命令:
 - 
任务: 使用不同的分隔符(例如
#或|)进行替换,当查找或替换内容包含/时特别有用。例如,更改日志中的 IP 地址192.168.1.254为10.10.0.10。- 命令:
sed 's|192\.168\.1\.254|10.10.0.10|' data.txt - 解释: 使用 
|作为s命令的分隔符,避免了转义/。仍然需要转义.。 
 - 命令:
 - 
任务: 只在包含 "ERROR" 的行中,将 "Failed" 替换为 "Attempted"。
- 命令:
sed '/ERROR/ s/Failed/Attempted/' data.txt - 解释: 
/ERROR/是地址,s命令只应用于匹配该地址的行。 
 - 命令:
 
场景 4: 同时执行多个命令
可以用分号 ; 或 -e 选项来执行多个 sed 命令。
- 任务: 删除所有空行,并将 "WARN" 替换为 "Warning"。
- 命令 (使用分号):
sed '/^$/d ; s/WARN/Warning/g' data.txt - 命令 (使用 -e):
sed -e '/^$/d' -e 's/WARN/Warning/g' data.txt - 解释: 两个命令按顺序在每一行上执行。
 
 - 命令 (使用分号):
 
场景 5: 插入和追加文本 (i, a)
i(insert): 在匹配行的 上方 插入文本。a(append): 在匹配行的 下方 追加文本。
- 
任务: 在文件的第一行之前插入一行 "# File managed by Sed script"。
- 命令:
sed '1i # File managed by Sed script' data.txt - 解释: 
1是行地址,i表示插入,后面是插入的文本。 
 - 命令:
 - 
任务: 在包含 "[Server]" 的那一行之后追加一行 "EnableKeepAlive=true"。
- 命令:
sed '/\[Server]/a EnableKeepAlive=true' data.txt - 解释: 
/\[Server]/是地址,a表示追加,后面是追加的文本。 
 - 命令:
 
场景 6: 修改整行 (c)
c (change) 命令会用新文本替换掉整个匹配的行。
- 任务: 将包含 "DebugMode=false" 的整行替换为 "DebugMode=true # Enabled for testing"。
- 命令:
sed '/DebugMode=false/c DebugMode=true # Enabled for testing' data.txt - 解释: 
/DebugMode=false/是地址,c表示替换整行,后面是新的行内容。 
 - 命令:
 
场景 7: 文件内编辑 (-i)
警告: -i 会直接修改原始文件!请务必小心,最好先进行测试。
- 任务: 直接在 
data.txt文件中,将所有 "bob" 替换为 "robert",并创建一个备份文件data.txt.bak。- 命令:
sed -i.bak 's/bob/robert/g' data.txt - 解释: 
-i.bak表示进行原地编辑,并在编辑前将原始文件备份为data.txt.bak。如果只想原地编辑不备份(不推荐),则只用-i。 
 - 命令:
 
总结与建议
- 从简单的打印 (
pwith-n) 和删除 (d) 开始,熟悉行地址的概念(数字、正则表达式、范围)。 - 重点掌握替换 (
s) 命令,它是sed的核心。练习不同的查找模式、替换字符串和标志 (g)。注意特殊字符的转义。 - 理解 
sed默认逐行处理并输出到标准输出的模式。 - 谨慎使用 
-i进行原地编辑,优先使用备份-i.bak。 - 尝试组合使用地址和命令,例如 
/pattern/ s/.../.../。 - 利用分号 
;或-e执行多个命令。 sed的正则表达式默认是基本正则表达式 (BRE)。某些特性(如+,?,|)需要转义 (\+,\?,\|) 或使用-E选项启用扩展正则表达式 (ERE)(GNU sed)。
现在,你可以在你的电脑上打开终端,创建 data.txt 文件,然后逐一执行上面的命令,观察输出结果。修改命令进行试验,这是最好的学习方式!祝你学习顺利!