概述
sed
是一种非交互式流编辑器,与交互式编辑器(如 vi
)完全不同。sed
处理文本是以行为单位,通过设定的若干组规则来编辑数据流。sed
是 stream editor
的缩写。
sed
可做的编辑工作包括删除、查找、替换、添加、插入、从其他文件读入数据等。默认情况下,sed
不会改变原文件内容,只是会把修改后的结果打印到屏幕上。
sed
命令的工作流程如下:
- 从输入中读取一行数据
- 根据编辑器命令匹配数据
- 根据命令修改流中的数据
- 将新的数据输出到标准输出(屏幕)
- 读取下一行数据并重复该过程
语法
该命令的语法如下:
sed [选项] '命令' [sed文件]
该命令支持的选项有:
选项 | 说明 |
---|---|
-e 脚本命令 | 该选项会将其后跟的脚本命令添加到已有的命令中。 |
-f 脚本命令文件 | 该选项会将其后文件中的脚本命令添加到已有的命令中。 |
-n | 默认情况下,sed 会在所有的脚本指定执行完毕后,会自动输出处理后的内容,而该选项会屏蔽启动输出,需使用 print 命令来完成输出。 |
-i | 此选项会直接修改源文件,要慎用。 |
sed
命令支持的命令有:
命令 | 说明 |
---|---|
a | 在匹配行之后添加新行 |
c | 替换匹配行之间的所有内容 |
d | 删除匹配行 |
i | 在匹配行之前插入新行 |
p | 打印匹配行,通常与 -n 选项一起使用 |
s | 替换匹配的文本 |
使用
连接多个编辑命令
使用 -e
选项或者分号 ;
连接多个编辑命令。命令格式如下:
sed -e 编辑命令1 -e 编辑命令2 ...
# 或
sed '编辑命令1;编辑命令2;...'
示例如下:
# 将所有的 this 替换成 That
echo "this is a test,that is a test too." | sed -e 's/this/That/g'
# 将所有的 this 替换成 That,同时将所有的 is 替换成 IS
echo "this is a test,that is a test too." | sed -e 's/this/That/g' -e 's/is/IS/g'
# 上句等价于下句,分号用于连接多条编辑指令
echo "this is a test,that is a test too." | sed 's/this/That/g;s/is/IS/g'
删除
使用 d
命令删除指定行。命令格式如下:
# 删除第 n 行
sed 'nd'
# 删除前 n 行内容
sed '1,nd'
# 删除第 i 行和第 j 行内容
sed -e 'id' -e 'jd'
# 删除第一行到最后一行的所有内容,相当于清空文件
sed '1,$d'
# 删除最后以行
sed '$d'
# 只保留第 n 行,其他全删除
sed 'n!d'
# 删除所有空白行
sed '/^$/d'
# 删除所有包含指定字符串 str 的行
sed '/str/d'
对于测试文件 test.txt
:
hello world
hello java
hello c++
hello python
hello html
sed
命令示例如下:
# 删除第 1 行
cat test.txt | sed '1d'
# 删除前 3 行内容
cat test.txt | sed '1,3d'
# 删除第 1 行和第 3 行内容
cat test.txt | sed -e '1d' -e '3d'
# 删除第一行到最后一行的所有内容,相当于清空文件
cat test.txt | sed '1,$d'
# 删除最后以行
cat test.txt | sed '$d'
# 只保留第 n 行,其他全删除
cat test.txt | sed '3!d'
# 删除所有空白行
cat test.txt | sed '/^$/d'
# 删除所有包含指定字符串 java 的行
cat test.txt | sed '/java/d'
查找替换
使用 s
命令可以将查找到的匹配文本内容替换为新的文本。命令格式如下:
# 默认情况下,只替换第一次出现的字符串
sed 's/旧字符串/新字符串/'
# 指定要替换的位置
sed 's/旧字符串/新字符串/出现次数'
# 删除指定字符串
sed 's/旧字符串//g'
# 将所有以指定字符串开头的字符串替换成新字符串
sed 's/^旧字符串/新字符串/g'
# 将第 i 行至第 j 行中的旧字符串替换成新字符串
sed 'i,js/旧字符串/新字符串/g'
# 将第 i 行至最后以行的旧字符串替换成新字符串
sed 'i,$s/旧字符串/新字符串/g'
对于测试文件 test.txt
:
hello world, hello java
hello c++, hello python, hello html
示例如下:
# 默认情况下,只替换每行中第一次出现的字符串
cat test.txt | sed 's/hello/HELLO/'
# 指定要替换的位置,替换每行中第 2 次出现的字符串
cat test.txt | sed 's/hello/HELLO/2'
# 删除指定字符串
cat test.txt | sed 's/hello//g'
# 将所有以指定字符串开头的字符串替换成新字符串
cat test.txt | sed 's/^hello/HI/g'
# 将第 1 行至第 2 行中的旧字符串替换成新字符串
cat test.txt | sed '1,2s/hello/hi/g'
# 将第 2 行至最后以行的旧字符串替换成新字符串
cat test.txt | sed '2,$s/hello/hi/g'
字符替换
可以使用 y
命令把一系列字符逐个变换成另一系列的字符。命令格式如下:
# 语法
# 将 o 替换成 n
# 将 l 替换成 e
# 将 d 替换成 w
sed 'y/old/new/'
# 示例
echo "hello" | sed 'y/he/12/'
注:
old
字符串和new
字符串的长度必须一致,否则将会报错strings for 'y' command are different lengths
。
插入文本
使用 i
或者 a
命令可以插入文件不。其中 i
表示在匹配行之前插入;a
表示在匹配行之后插入。其中匹配模式支持正则表达。命令格式如下:
# 使用 i 命令在第 m 行之前插入文本
sed 'm i 待插入的文本' 文件名
# 使用 a 命令在第 m 行之后插入文本
sed 'm a 待插入的文本' 文件名
# 在匹配上的上一行插入文本
sed '/匹配模式/i\待插入的文本' 文件名
# 在匹配的下一行插入文本
sed '/匹配模式/a\待插入的文本' 文件名
对于测试文件 test.txt
:
hello world
hello java
hello c++
hello python
hello html
示例如下:
# 使用 i 命令在第 2 行之前插入文本 "HELLO ZHANGSAN"
sed '2 i HELLO ZHANGSAN' test.txt
# 使用 a 命令在第 2 行之后插入文本 "HELLO ZHANGSAN"
sed '2 i HELLO ZHANGSAN' test.txt
# 在匹配上的上一行插入文本 "HELLO ZHANGSAN"
sed '/java/i\HELLO ZHANGSAN' test.txt
# 在匹配的下一行插入文本 "HELLO ZHANGSAN"
sed '/java/a\HELLO ZHANGSAN' test.txt
修改行
可以使用 c
命令(change
)对整行内容进行修改。命令格式如下:
# 对第 m 行的整行内容进行修改
sed 'mc\新行内容' 文件名
# 对第 i 到第 j 行的内容进行替换
sed 'i,jc\新行内容' 文件名
# 将包含指定字符串 str 的行替换成新内容
sed '/匹配模式/c\新行内容' 文件名
对于测试文件 test.txt
:
hello world
hello java
hello c++
hello python
hello html
示例如下:
# 对第 2 行的整行内容进行修改为 "HELLO ZHANGSAN"
sed '2c\HELLO ZHANGSAN' test.txt
# 对第 2 到第 3 行的内容进行替换,替换为 "HELLO ZHANGSAN"
sed '2,4c\HELLO ZHANGSAN' test.txt
# 将包含指定字符串 java 的行替换成新内容 "HELLO ZHANGSAN"
sed '/java/c\HELLO ZHANGSAN' test.txt
写入文本
使用 r
命令可以从其他文件中读取文本并插入至匹配行后。匹配模式是匹配指定文件中的行,而 sed
命令会把其他文件所有行都写入。命令格式如下:
# 语法
sed '/匹配模式/r 其他文件' 指定文件名
# 示例
sed '/java/r /etc/passwd' test.txt
打印
p
命令示搜索符号条件的行,并输出该行的内容,通常与 -n
选项一起使用,我们可以禁止输出其他行,只打印包含匹配文本模式的行。命令格式如下:
# 语法
sed -n '/匹配模式/p' 文件名
# 示例,只打印文件中包含 java 的行
sed -n '/java/p' test.txt
写文件
w
命令可以用来将文本中指定行的内容写入文件。命令格式如下:
# 将第 i 到 j 行的内容写入文件
sed 'i,jw 待写入文件路径' 文件名
# 示例,将 test.txt 文件的第 2 到 3 行的内容写入 abc.txt
sed '2,3w abc.txt' test.txt