文章目录
sed是一个流编辑器,用于对文件或输入流执行各种文本转换,功能强大且效率高。
主要用于对数据行进行替换、删除、新增、修改等。
一、sed 语法格式
sed [-nefri] 'command' 输入文本
参数选项
常见参数 | 说明 |
---|---|
-n | 抑制输出,结合p 指令打印特定行。默认sed会列出所有指定内容,加上 -n 参数后,则只有经过sed 特殊处理的那一行才会被列出来。 |
-i | 直接修改文件内容,而且不进行任何输出,慎用! 默认情况下 sed 并不直接修改文件内容,只是把结果进行标准输出,文件内容实际没有变化。 |
-e | 使用后面的动作指令编辑文件内容 |
-f | 直接将 sed 的动作写在一个档案内, -f filename 则可以执行 filename 内的sed 动作; |
动作指令
- 使用时要用单引号把动作指令内容括起来;
- 若指令内容包含变量,则用双引号括起来。
常用动作 | 说明 |
---|---|
p | print,打印,列出指定的内容,通常与 -n 参数一起使用 |
a | after,新增,后面接字符串,并显示在新的一行(目前的下一行) |
i | insert,插入, 后面接字符串,并显示在新的一行(目前的上一行) |
c | change,替换一行或多行的整行内容,后面接字符串,用于取代 n1,n2 之间的行 |
s | supersede,stead,替换一行或多行中的部分内容,通常搭配正规表达式 常用方式: 1,20s/old/new/g |
d | delete,删除,后面通常不接任何字符 |
二、参数使用举例
(假设我们有一文件名为input)
1、输入文件的几种方式
sed 命令中的文件参数可以是文件名,也可以是来自管道的输入。
下面几种方式是等价的:
sed 's/hello/world/g' input > output
sed 's/hello/world/g' < input> output
cat input | sed 's/hello/world/g' - > output
cat input | sed 's/hello/world/g' > output # - 可以省略
2、-n 抑制输出
默认情况下,sed打印所有已处理的输入(已通过命令修改/删除的输入除外)。
使用 -n 抑制输出,结合p
指令可以打印特定行。
仅打印输入文件的第45行:
sed -n '45p' input
3、-i 修改文件内容且不进行输出
- 直接修改文件内容,而且不进行任何输出,慎用!
- 可以与其它指令结合使用。
- 单独使用其它参数和指令都不会直接修改文件内容。
- 当文件很大时,使用类似 vim 的命令修改文件很不方便,此时使用 sed -i 就非常方便,可以不用打开文件,直接实现修改/取代的功能。
查看input文件原内容:
$ cat input
hello ehllo hello
hello abadbsabf
a123gdsgahello
sed 不带 -i 参数时进行替换指令
会输出替换后的结果,且再次查看input内容,原文件未修改。
# sed 替换
$ sed 's/hello/world/' input
world ehllo hello
world abadbsabf
a123gdsgaworld
# 查看input内容,并未真正修改
$ cat input
hello ehllo hello
hello abadbsabf
a123gdsgahello
sed -i 进行替换指令
不会输出任何内容,且再次查看input内容,原文件直接被修改了。
$ sed -i 's/hello/world/' input
$ cat input
world ehllo hello
world abadbsabf
a123gdsgaworld
sed -i 使用正则表达式匹配
- 使用
sed -i 's/\.$/\!/g'
将结尾为.
的行替换成以!
结尾
$ cat input.txt
google.
taobao.
zhihu-
$ sed -i 's/\.$/\!/g' input.txt
$ cat input.txt
google!
taobao!
zhihu-
- 使用
sed -i '$a # This is a test'
直接在文件最后一行增加 # This is a test:
(这个命令把选项 -i 和指令 a 结合使用,同时其中 $ 代表最后一行,从而实现直接修改文件,在最后一行后面新增内容。)
$ sed -i '$a # This is a test' input.txt
$ cat input.txt
google!
taobao!
zhihu-
# This is a test
4、-e 和 -f 指定脚本
4.1 语法:
-e 指定动作集(两种方式一样):
- -e script
- –expression=script
-f 指定动作文件(两种方式一样):
- -f script-file
- –file=script-file
4.2 下面几种示例是等价的:
sed 's/hello/world/' input.txt > output.txt
sed -e 's/hello/world/' input.txt > output.txt
sed --expression='s/hello/world/' input.txt > output.txt
echo 's/hello/world/' > myscript.sed
sed -f myscript.sed input.txt > output.txt
sed --file=myscript.sed input.txt > output.txt
4.3 使用 -e
实现多个匹配
默认情况下,一条sed命令只能有一个编辑指令;
若要实现同时执行多个编辑指令,有如下几种方式:
- 通过 -f 指定脚本文件,在文件中集合多条指令;
- 通过管道符
|
连接多条 sed 指令; - 在一条sed指令中使用多个
-e
选项实现。
在一条sed命令中,删除/etc/passwd第三行到末尾的数据,并把bash替换为blueshell:
$ nl /etc/passwd | sed -e '3,$d' -e 's/bash/blueshell/'
1 root:x:0:0:root:/root:/bin/blueshell
2 daemon:x:1:1:daemon:/usr/sbin:/bin/sh
三、各指令使用举例
1、p
打印某行
p
–print,通常与-n
一起使用, -n ‘1,Np’- 可以使用内容匹配模式打印出包含指定内容的行,用
/ /
来包含关键字 - 当使用模式匹配时,如果要匹配的关键字符串包含有变量,则需要用双引号"",而不是单引号’’,其它命令中也是类似的。
命令 | 说明 |
---|---|
sed ‘1p’ filename | 先打印第一行,然后再打印所有行 |
sed -n ‘1p’ filename | 打印第一行 |
sed -n ‘$p’ filename | 打印最后一行 |
sed -n ‘1,2p’ filename | 打印第一行到第二行 |
sed -n ‘2,$p’ filename | 打印第二行到最后一行 |
sed ‘/yuance/p’ filename | 先打印包含yuance 的行,再打印所有行 |
sed -n ‘/yuance/p’ filename | 打印包含yuance 的行 |
sed -n ‘/$/p’ filename | 打印包括关键字 $ 所在的行,使用反斜线 \ 屏蔽特殊含义 |
2、d
删除某行
d
--delete, 可指定区间,‘1,Nd’- 与
p
指令用法类似 - 默认会打印出删除指定行后,其它行的内容,但是原文件内容不变
命令 | 说明 |
---|---|
sed ‘3d’ filename | 删除第三行 |
sed ‘$d’ filename | 删除最后一行 |
sed ‘1,2d’ filename | 删除第一行到第二行 |
sed ‘2,$d’ filename | 删除第二行到最后一行 |
sed ‘/pattern/d’ filename | 删除包含pattern关键字的所有行 |
$ cat input
world ehllo hello
world abadbsabf
a123gdsgaworld
1241
$ sed '4d' input
world ehllo hello
world abadbsabf
a123gdsgaworld
$ cat input
world ehllo hello
world abadbsabf
a123gdsgaworld
1241
3、a
增加一行或多行字符串(在下一行)
a
--after, 可指定区间,‘1,Na xxx’- 直接在
''
引号内跟上要增加的字符串 - 同样的,并不改变原文件内容
- 需要增加多行时,使用换行符
\n
,且前后不带空格,若加上空格会被当作增加的有效字符。
命令 | 说明 |
---|---|
sed ‘1a drink tea’ filename | 第一行后增加字符串"drink tea" |
sed ‘1,3a drink tea’ filename | 第一行到第三行后增加字符串"drink tea" |
sed ‘$a drink bye’ filename | 最后一行后增加字符串"bye" |
sed ‘1a drink tea\nor coffee’ filename | 第一行后增加两行"drink tea"和"or coffee" |
sed ‘1a drink tea’ filename | 第一行后增加字符串"drink tea" |
$ cat input.txt
Hello!
jing is me,welcome to my blog.
end
第一行后增加字符串"drink tea"
$ sed '1a drink tea' input.txt
Hello!
drink tea
jing is me,welcome to my blog.
end
第一行到第三行后增加字符串"drink tea"
$ sed '1,3a drink tea' input.txt
Hello!
drink tea
jing is me,welcome to my blog.
drink tea
end
drink tea
增加多行,使用换行符 "\n"
$ sed '1a drink tea\nor coffee' input.txt
Hello!
drink tea
or coffee
jing is me,welcome to my blog.
end
4、i
插入一行或多行(在上一行)
todo
i
--insert, 可指定区间,‘1,Na xxx’- 直接在
''
引号内跟上要增加的字符串 - 不会改变原文件内容
- 需要增加多行时,使用换行符
\n
,且前后不带空格,若加上空格会被当作增加的有效字符。
5、c
对一行或多行进行整行替换
c
--change, 以行为单位进行替换,可指定区间, ‘1,Nc’- 直接在
''
引号内跟上要替换后的字符串 - 同样的,并不改变原文件内容
- 需要增加多行时,使用换行符
\n
,且前后不带空格,若加上空格会被当作增加的有效字符。
第一行代替为 "Hi"
$ sed '1c Hi' input.txt
Hi
jing is me,welcome to my blog.
end
第一行到第二行代替为 "Hi"
$ sed '1,2c Hi' ab
Hi
end
将第2-5行的内容取代成为"No 2-5 number"(其中"nl"是带行号输出):
$ nl /etc/passwd | sed '2,5c No 2-5 number'
1 root:x:0:0:root:/root:/bin/bash
No 2-5 number
6 sync:x:5:0:sync:/sbin:/bin/sync
.....(后面省略).....
6、s
替换一行中的部分内容
6.1 格式 ‘s/xx/xx/g’:
sed 's/要替换的字符串/新的字符串/g' (要替换的字符串可以用正则表达式)
- 其中
g
表示global
全局替换,否则只替换每行的第一处。 g
可以换成具体的数据,指定在每行的第几个匹配项处进行替换
命令 | 说明 |
---|---|
sed ‘s/cat/bird/g’ filename | 把文件中所有的’cat’替换成’bird’ |
sed ‘s/cat//g’ filename | 删除文件中所有的’cat’(替换为空即删除) |
sed ‘s/unix/linux/’ filename | 把每一行中的第 1 次出现的’unix’替换成’linux’ |
sed ‘s/unix/linux/3’ filename | 把每一行中的第 3 次出现的’unix’替换成’linux’ |
sed ‘s/unix/linux/4g’ filename | 把每一行中第 4 次开始到最后出现的’unix’全部替换成’linux’ |
sed ‘3 s/unix/linux/’ filename | 在’s’前加数字,可对指定行进行替换。 把第 3 行中第一次出现的’unix’替换成’linux’。 |
sed ‘3,7 s/unix/linux/’ filename | 在’s’前也可以加数字范围,对多行进行替换。 把第 3-7 行中第一次出现的’unix’替换成’linux’。 |
sed ‘3,$ s/unix/linux/’ filename | 把第 3行至结尾行每行第一次出现的’unix’替换成’linux’。 |
nl filename | sed -n ‘7 s/unix/linux/p’ | 把第 7 行中第一次出现的’unix’替换成’linux’,并把替换后的第7行打印出来。 若加了 -n 不加的后面的 p ,则替换后不打印。 |
6.2 匹配字符串中使用正则表达式
原字符串 | 命令 | 匹配结果 |
---|---|---|
inet addr:192.168.1.100 | sed 's/^.*addr://g’ | 192.168.1.100 |
192.168.1.100 Bcast:192.168.1.255 | sed 's/Bcast.*$//g’ | 192.168.1.100 |
hello world | sed 's/^/#/g’ | #hello world ,即在每行开头加上 # |
hello world | sed 's/$/—/g’ | hello world--- ,即在每行最后加上 — |
6.3 替换匹配行中的某个字符串
sed '/匹配字符串/s/替换源字符串/替换目标字符串/g' filename
- 先进行字符串匹配;
- 然后对匹配到的行进行字符串替换。