Linux shell sed 命令基础
sed(Stream EDitor)是 Linux/Unix 系统中一个非常强大且常用的流编辑器。它主要用于对文本进行过滤和转换,
即读取输入流(文件或管道),按照指定的命令进行处理,然后将结果输出
核心概念和工作原理
流式处理:sed 逐行处理文本,不会一次性将整个文件加载到内存中,因此非常适合处理大文件。
模式空间:sed 维护一个叫做“模式空间”的缓冲区。它读取一行文本到模式空间,在那里应用所有给定的命令,然后输出模式空间的内容(除非被特别抑制),接着处理下一行。
非交互式:与 vi 或 nano 不同,你通过命令行预先写好所有编辑指令,sed 自动执行,非常适合脚本操作。
基本语法
sed [选项] '命令' 输入文件
sed [选项] -e '命令1' -e '命令2' ... 输入文件 # 多个命令
sed [选项] -f 脚本文件 输入文件 # 从文件读取命令
常用选项
选项    全称    说明
-n    --quiet, --silent    静默模式。默认情况下,sed 会输出所有行。加上 -n 后,只有被 p 命令处理过的行才会被显示。
-e    --expression    指定要执行的命令,用于连接多个命令。
-i    --in-place    直接修改文件(危险但强大)。通常建议用 -i.bak 先创建备份。
-r    --regexp-extended    使用扩展正则表达式(ERE),而不是默认的基本正则表达式(BRE),功能更强,语法更简洁。
-f    --file    从指定文件中读取 sed 脚本。
常用命令
命令必须跟在选项后面,用单引号括起来。
命令    语法    说明
替换    s/原模式/替换内容/标志    最常用的命令。将匹配“原模式”的文本替换为“替换内容”。
删除    d    删除模式空间中的当前行,立即开始下一轮循环。
打印    p    打印当前模式空间的内容。通常与 -n 选项一起使用。
行号    =    打印当前行的行号。
插入    i\文本    在指定行之前插入文本。
追加    a\文本    在指定行之后追加文本。
读文件    r 文件名    将指定文件的内容读取并插入到匹配行之后。
写文件    w 文件名    将匹配行的内容写入到指定文件中。
退出    q [退出码]    在处理到指定行后立即退出 sed。
转换    y/原字符集/新字符集/    类似 tr 命令,进行字符一对一转换。
地址定界
sed 命令可以指定只对某些行进行操作,这就是地址定界。如果省略,则命令会应用于所有行。
n    一个数字,表示第 n 行。    sed -n '5p' file # 只打印第5行
n,m    从第 n 行到第 m 行。    sed '10,20d' file # 删除10到20行
n,+m    从第 n 行到第 n+m 行。    sed '5,+3d' file # 删除5到8行
$    最后一行。    sed '$d' file # 删除最后一行
/regex/    匹配正则表达式 regex 的行。    sed '/^#/d' file # 删除所有注释行(以#开头)
addr1,addr2    从匹配 addr1 的行开始,到匹配 addr2 的行结束。    sed '/start/,/end/d' file # 删除从包含"start"到包含"end"的所有行
n~m    从第 n 行开始,步长为 m。    sed -n '1~2p' file # 打印所有奇数行(第1,3,5...行)
替换命令 (s///) 的详解和标志
s/pattern/replacement/flags
标志    说明
g    全局替换。一行中所有匹配项都会被替换,而不仅仅是第一个。
p    打印替换发生后的当前模式空间。通常与 -n 选项一起使用。
w 文件名    将成功替换的行写入到指定文件。
i 或 I    匹配 pattern 时忽略大小写。
数字    一个数字(如1,2),表示只替换第N个匹配项。
替换内容中的特殊字符:
&: 代表匹配到的整个内容。
\1, \2, ... \9: 代表正则表达式中用 \( 和 \) 分组的内容。
经典案例
假设我们有一个文件 test.txt,内容如下:
Hello world
This is a test file.
Welcome to the sed tutorial.
Linux is powerful.
Hello again.
test is important.
1. 替换操作
将每行的第一个 "Hello" 替换为 "Hi"
sed 's/Hello/Hi/' test.txt
将所有的 "is" 替换为 "IS"(全局替换)
sed 's/is/IS/g' test.txt
将 "Hello" 替换为 "Hi",并且只打印发生替换的行
sed -n 's/Hello/Hi/p' test.txt
将第一个单词和最后一个单词互换(使用分组)
# 假设一行只有两个单词
sed -r 's/^([^ ]+) (.*)$/\2 \1/' test.txt
# 更通用的:交换第一个和最后一个字段(以空格分隔)
sed -r 's/^([^ ]+)(.* )([^ ]+)$/\3\2\1/' test.txt
在匹配到的内容前后添加字符(使用 &)
# 将 "Linux" 替换为 "[Linux]"
sed 's/Linux/[&]/g' test.txt
删除操作
删除第3行
sed '3d' test.txt
删除包含 "test" 的行
sed '/test/d' test.txt
删除从第2行到包含 "tutorial" 的行
sed '2,/tutorial/d' test.txt
删除所有空行
sed '/^$/d' test.txt
打印和其他操作
只打印第2到第4行
sed -n '2,4p' test.txt
打印包含 "is" 的行,并显示行号
sed -n '/is/{=;p}' test.txt
# 或者用分号分隔命令
sed -n '/is/=' test.txt # 只打印行号
sed -n '/is/p' test.txt # 只打印内容
在第2行之后插入一行 "--- INSERTED LINE ---"
sed '2a\--- INSERTED LINE ---' test.txt
在第1行之前插入一行 "--- START ---"
sed '1i\--- START ---' test.txt
文件操作
将包含 "Hello" 的行写入到新文件 hello.txt
sed -n '/Hello/w hello.txt' test.txt
在最后一行之后插入另一个文件 other.txt 的内容
sed '$r other.txt' test.txt
原地修改文件(-i 选项)
⚠️ 警告:此操作会直接修改原文件,务必小心!
直接修改文件,将所有 "is" 替换为 "IS"
sed -i 's/is/IS/g' test.txt
更安全的做法:先备份原文件(备份文件为 test.txt.bak)
sed -i.bak 's/is/IS/g' test.txt
综合案例
清理配置文件:删除所有注释和空行
# 假设注释以 # 开头
sed -e '/^#/d' -e '/^$/d' config.conf
# 或者
sed '/^#/d; /^$/d' config.conf
修改特定范围的行:将1到3行的 "Hello" 替换为 "Greetings"
sed '1,3s/Hello/Greetings/g' test.txt
使用脚本文件:将复杂的命令写在 script.sed 文件中
# script.sed 内容:
# s/Hello/Hi/g
# /test/d
sed -f script.sed test.txt
总结
sed 的核心在于 s///(替换)、d(删除) 和 p(打印) 这三个命令,结合地址定界和正则表达式,可以完成绝大多数文本处理任务。
最佳实践:
在不使用 -i 选项时先测试命令,确认无误后再用 -i。
使用 -i.bak 创建备份是一个好习惯。
对于复杂的多步操作,使用 -e 连接多个命令或使用 -f 脚本文件
