3.sed 使用手册

3.sed 使用手册

sed 介绍

文章目录

  • [3.sed 使用手册](#3.sed 使用手册)
    • [sed 介绍](#sed 介绍)
    • [sed 工作流程](#sed 工作流程)
    • [sed 注意事项](#sed 注意事项)
    • [sed 命令语法](#sed 命令语法)
      • 准备文件
      • [-e 选项](#-e 选项)
      • [-n 选项](#-n 选项)
    • [sed 行寻址](#sed 行寻址)
    • [sed 子命令](#sed 子命令)

sed,英文全称 stream editor ,是一种非交互式的流编辑器,能够实现对文本非交互式的处理,功能很强大。

Linux操作文本的三大利器,简称三剑客,分别是:

  • grep:擅长过滤。
  • sed:擅长修改文本。
  • awk:擅长格式化输出。

sed 与 awk 并称为 Linux/Unix 世界的两大王牌文字处理器:

  • sed 侧重点是替换。
  • awk 侧重点是分割和重新合成。

sed 工作流程

sed 工作流程,说起来很简单。

复制代码
读取行 -> 执行 -> 显示 -> 读取行 -> 执行 -> 显示 -> .... -> 读取行 -> 执行 -> 显示
  1. 读取行

    sed 从输入流 (文件、管道、标准输入流)中读取 一行 并存储在名叫 pattern space 的内部空间中。

    sed 是行文字处理器。每次只会读取一行。

    sed 内部会有一个计数器,记录着当前已经处理多少行,也就是当前行的行号。

  2. 执行

    按照 sed 命令定义的顺序依次应用于刚刚读取的 一行 数据。

    默认情况下,sed 一行一行的处理所有的输入数据。但如果我们指定了行号,则只会处理指定的行。

  3. 显示

    把经过 sed 命令处理的数据发送到输出流(文件、管道、标准输出),并同时清空 pattern space 空间。

  4. 上面流程一直循环,直到输入流中的数据全部处理完成。

sed 注意事项

整个流程看似简单,有几个知识点需要注意:

  • pattern space 空间是 sed 在内存中开辟的一个私有的存储区域。内存的特性,会导致关闭命令行或关机数据就没了。

  • 默认情况下,sed 命令只会处理 pattern space 空间中的数据,且并不会将处理后的数据保存到源文件中。也就是说,sed 默认并不会修改源文件。

    但 GNU SED 提供提供了一种方式用于修改 源文件 。方式就是传递 -i 选项,在后面的章节中介绍。

  • sed 还在内存上开辟了另一个私有的空间 hold space 用于保存处理后的数据以供以后检索。

    每一个周期执行结束,sed 会清空 pattern space 空间的内容,但 hold space 空间的内容并不会清空。hold space 空间用于存储处理后数据,sed 命令并不会对这里的数据处理。

    这样,当 sed 需要之前处理后的数据时,可以随时从 hold space 空间读取。

  • sed 程序执行前,模式 patternhold space 空间都是空的。

  • 如果我们没有传递任何输入文件,sed 默认会从 标准输入 中读取数据。

  • sed 可以指定只处理输入数据中的行范围。默认情况下是全部行,因此会依次处理每一行。

sed 命令语法

bash 复制代码
-n, --quiet, --silent    取消自动打印模式空间
 -e 脚本, --expression=脚本   添加"脚本"到程序的运行列表
 -f 脚本文件, --file=脚本文件  添加"脚本文件"到程序的运行列表
 --follow-symlinks    直接修改文件时跟随软链接
 -i[扩展名], --in-place[=扩展名]    直接修改文件(如果指定扩展名就备份文件)
 -l N, --line-length=N   指定"l"命令的换行期望长度
 --posix  关闭所有 GNU 扩展
 -r, --regexp-extended  在脚本中使用扩展正则表达式
 -s, --separate  将输入文件视为各个独立的文件而不是一个长的连续输入
 -u, --unspaceed  从输入文件读取最少的数据,更频繁的刷新输出
 --help     打印帮助并退出
 --version  输出版本信息并退出
 -a ∶新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
 -c ∶取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
 -d ∶删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
 -i ∶插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
 -p ∶列印,亦即将某个选择的资料印出。通常 p 会与参数 sed -n 一起运作~
 -s ∶取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法
bash 复制代码
sed [option] [sed-command] [input-file]

总的来说 sed 命令主要由四部分构成:

  1. sed 命令。
  2. [option] 命令行选项,用于改变 sed 的工作流程。
  3. [sed-command] 是具体的 sed 命令。
  4. [input-file] 输入数据,如果不指定,则默认从标准输入中读取。

准备文件

bash 复制代码
[root@server ~ 11:12:34]# cat > data.txt <<'EOF'
> I am studing sed
> I am www.laoma.cloud
> I am a Superman
> I am so handsome
> EOF

#不指明,直接打印
[root@server ~ 11:26:37]# sed '' data.txt 
I am studing sed
I am www.laoma.cloud
I am a Superman
I am so handsome

-e 选项

从命令行读取sed命令,我们需要将 sed 命令使用单引号 ( '' ) 引起来。

bash 复制代码
#删除第一行
[root@server ~ 11:30:04]# sed '1d' data.txt 
I am www.laoma.cloud
I am a Superman
I am so handsome

#删除第一行和第二行
[root@server ~ 11:30:11]# sed '1d;2d' data.txt 
I am a Superman
I am so handsome
#或者
[root@server ~ 11:30:34]# sed -e '1d' -e '2d' data.txt 
I am a Superman
I am so handsome

-n 选项

如果指定了该选项,那么模式空间数据将不会自动打印,需要明确指明打印才会输出记录。

bash 复制代码
[root@server ~ 11:30:40]# sed -n '' data.txt 

#指明打印第一行
[root@server ~ 11:34:23]# sed -n '1p' data.txt 
I am studing sed

#默认打印,再打印第一行
[root@server ~ 11:34:31]# sed  '1p' data.txt 
I am studing sed
I am studing sed
I am www.laoma.cloud
I am a Superman
I am so handsome

sed 行寻址

作用

通过行寻址匹配要处理的输入流。

语法

这里以打印命令p为例。

语法:[address1[,address2]]p

  • address1address2 分别是 起始地址结束地址 ,可以是 行号模式字符串
  • address1address2 都是可选参数,可以都不填,这时候就是打印所有行,从文件的开头到文件结束。
  • 如果存在一个,那么就是打印 单行 。也就是只打印 address1 指定的那行。
  • p 命令仅从 模式缓冲区 中打印行,也就是该行不会发送到输出流,原始文件保持不变。

示例文件

bash 复制代码
[root@server ~ 13:33:18]#  echo 'This is 1    
> This is 2    
> This is 3
> This is 4
> This is 5 ' > test

演示

示例1: 打印所有行

bash 复制代码
[root@server ~ 14:09:16]# cat test | sed ''
This is 1    
This is 2    
This is 3
This is 4
This is 5 
[root@server ~ 14:09:32]# cat test | sed -n 'p'
This is 1    
This is 2    
This is 3
This is 4
This is 5 

示例2: 打印特定行

bash 复制代码
[root@server ~ 14:09:49]# cat test | sed -n '1p'
This is 1

示例3: 打印第1行到3行

bash 复制代码
[root@server ~ 14:10:49]# cat test | sed -n '1,3p' 
This is 1    
This is 2    
This is 3

示例4: 打印第3行到最后一行

bash 复制代码
[root@server ~ 14:11:55]# cat test | sed -n '3,$p' 
This is 3
This is 4
This is 5 

示例5: 连续输出,打印第2行以及后续两行

bash 复制代码
[root@server ~ 14:12:35]# cat test | sed -n '2,+2p'
This is 2    
This is 3
This is 4

示例6: 隔行输出,打印第1行以及后续隔2行输出

bash 复制代码
[root@server ~ 14:12:44]# cat test | sed -n '1~2p' 
This is 1    
This is 3
This is 5 

sed 子命令

打印

作用
  • p,打印模式空间所有记录。
  • P,打印模式空间第一行记录。
语法

格式:[address1[,address2]]p

  • address1address2 分别是 起始地址结束地址 ,可以是 行号模式字符串
  • address1address2 都是可选参数,可以都不填,这时候就是打印所有行,从文件的开头到文件结束。
  • 如果存在一个,那么就是打印 单行 。也就是只打印 address1 指定的那行。
  • p 命令仅从 模式缓冲区 中打印行,也就是该行不会发送到输出流,原始文件保持不变。
示例
bash 复制代码
[laoma@shell ~]$ cat << 'EOF' > ~/test
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
mail:x:8:12:mail:/var/spool/mail:/bin/false
ftp:x:14:11:ftp:/home/ftp:/bin/false
&nobody:$:99:99:nobody:/:/bin/false
zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash
http:x:33:33::/srv/http:/bin/false
dbus:x:81:81:System message bus:/:/bin/false
hal:x:82:82:HAL daemon:/:/bin/false
mysql:x:89:89::/var/lib/mysql:/bin/false
aaa:x:1001:1001::/home/aaa:/bin/bash
ba:x:1002:1002::/home/zhangy:/bin/bash
test:x:1003:1003::/home/test:/bin/bash
@zhangying:*:1004:1004::/home/test:/bin/bash
policykit:x:102:1005:Po
EOF

读取下一行

  • n ,提前读取下一行,**覆盖**模型空间之前读取的行。模型空间之前读取的行并没有删除,依然打印至标准输出,除非使用-n选项指明不打印。

示例1:打印偶数行内容

bash 复制代码
[root@server ~ 14:31:12]# echo 'This is 1
> This is 2
> This is 3
> This is 4
> This is 5' | sed -n 'n;p'

This is 2
This is 4

说明:

  • 读取 This is 1,执行n命令,此时模式空间为This is 2,执行p,打印模式空间内容This is 2
  • 之后读取 This is 3,执行 n 命令,此时模式空间为This is 4,执行p,打印模式空间内容This is 4
  • 之后读取 This is 5,执行 n 命令,因为后续没有内容了,所以退出,并放弃p命令。

因此,最终打印出来的就是偶数行。

  • N ,简单来说就是**追加下一行到模式空间,同时将两行看做一行,但是两行之间依然含有\n换行符。**

示例1: 成对合并行

bash 复制代码
[root@server ~ 14:30:46]# cat test | sed 'N;s/\n/==/'
root:x:0:0:root:/root:/bin/bash==bin:x:1:1:bin:/bin:/bin/false
...

说明:

  1. N,追加下一行到当前行后面,组成一个新行来处理。
  2. s/\n/==/,将新行中 \n 换行符替换成==,末尾的换行符不替换。

示例2: 打印前2行

bash 复制代码
[root@server ~ 14:30:25]# echo 'This is 1    
> This is 2    
> This is 3    
> This is 4    
> This is 5' | sed -n '1{N;p}'
This is 1    
This is 2  

替换

**示例1:**把test文件中的root替换成tankzhang,只不过只替换一次即终止在这一行的操作,并转到下一行

bash 复制代码
[root@server ~ 14:29:41]# sed 's/root/tankzhang/' test|grep tankzhang
tankzhang:x:0:0:root:/root:/bin/bash

关闭SELinux

bash 复制代码
sed -i 's/^SELINUX=.*/SELINUX=disabled/g' config

**示例2:**把test文件中的root全部替换成tankzhang。字母g是global的缩写

bash 复制代码
[root@server ~ 14:28:37]# sed 's/root/tankzhang/g' test |grep tankzhang
tankzhang:x:0:0:tankzhang:/tankzhang:/bin/bash

**示例3:**加了-np后表示只打印那些发生替换的行(部分替换),下面的例子,不需要使用grep命令

bash 复制代码
[root@server ~ 14:23:12]# sed -n 's/root/tankzhang/p' test
tankzhang:x:0:0:root:/root:/bin/bash

**示例4:**加了-npg后表示只打印那些发生替换的行(全部替换)

bash 复制代码
[root@server ~ 14:20:16]# cat test |sed -n 's/root/tankzhang/gp'
tankzhang:x:0:0:tankzhang:/tankzhang:/bin/bash

**示例5:**在第二行到第八行之间,替换以zhang开头的行,用ying来替换,并显示替换的行

bash 复制代码
[root@server ~ 14:28:53]# sed -ne '2,8s/^zhang/ying/gp' test
yingy:x:1000:100:,,,:/home/zhangy:/bin/bash

示例6: 从以zhang开头的行开始,到匹配Po的行结束,在他们之间进行替换

bash 复制代码
[root@server ~ 14:29:22]# sed -ne '/^zhang/,/Po/ s/zhang/ying/gp' test
yingy:x:1000:100:,,,:/home/yingy:/bin/bash
ba:x:1002:1002::/home/yingy:/bin/bash
@yingying:*:1004:1004::/home/test:/bin/bash

替换中的分隔符可以自定义,默认是/。

示例7: 自定义替换分隔符为 #

bash 复制代码
[root@server ~ 14:21:55]# ls -1 /etc/ho* | sed -n 's/c\/h/==/p'
/et==ost.conf
/et==ostname
/et==osts
/et==osts.allow
/et==osts.deny

[root@server ~ 14:22:41]# ls -1 /etc/ho* | sed -n 's#c/h#==#p'
/et==ost.conf
/et==ostname
/et==osts
/et==osts.allow
/et==osts.deny

分隔符 ; 和 -e 选项

需要执行多个sed处理命令 时,用分号分开 ,或者使用 -e 选项。

示例:

  • 在第2行到第8行之间,替换以zhang开头的行,用ying来替换
  • 在第5行到第10行之间,用goodbay来替换dbus,并显示替换的行
bash 复制代码

插入

a 在匹配行下面插入新行
bash 复制代码
[root@server ~ 14:31:50]# sed '/root/a====aaaa====' test
root:x:0:0:root:/root:/bin/bash
====aaaa====
i 在匹配行上面插入新行
bash 复制代码
[root@server ~ 15:18:03]# sed -nr '/root/i====iiii====\nroot/p' test
====iiii====
root/p

删除

作用
  • d,删除模式空间所有记录。
  • D,删除模式空间第一行记录。
语法

d 格式:[address1[,address2]]d

D 格式:[address1[,address2]]D

  • address1address2 分别是 起始地址结束地址 ,可以是 行号模式字符串
  • address1address2 都是可选参数,可以都不填,这时候就是删除所有行,从文件的开头到文件结束。
  • 如果存在一个,那么就是删除 单行 。也就是只删除 address1 指定的那行。
  • d 命令仅从 模式缓冲区 中删除行,也就是该行不会发送到输出流,原始文件保持不变。
d 删除 示例
bash 复制代码
# 删除1,14行
[root@server ~ 15:28:06]# sed -e '1,14d' test
[root@server ~ 16:14:39]# cat test 
====iiii====
root/p

#删除4以后的行,包括第4行,把$当成最大行数就行了
[root@server ~ 18:35:26]# cat test |sed -e '4,$d'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false

#删除包括false的行,或者包括bash的行,别忘了加\转义字符
[root@server ~ 18:37:50]# cat test |sed -e '/\(false\|bash\)/d'
policykit:x:102:1005:Po

#删除从匹配root的行,到匹配以test开头的行,中间的行
[root@server ~ 18:38:27]# cat test |sed -e '/root/,/^test/d'
@zhangying:*:1004:1004::/home/test:/bin/bash
policykit:x:102:1005:Po
使用 s 命令实现删除
bash 复制代码
#删除 test 文件中所有以 "root" 开头的行,同时删除文件中的所有空行
[root@server ~ 18:50:18]# cat test |sed -r 's/^root(.*)$//;/^$/d'

#删除特定字符串
[root@server ~ 18:50:27]# cat test |sed -nr 's/^root//gp'
:x:0:0:root:/root:/bin/bash
D 删除 示例

删除当前模式空间开端至\n的内容,放弃之后的命令,对剩余模式空间继续执行sed。

bash 复制代码
[root@server ~ 18:52:46]# echo 'This is 1    
> This is 2    
> This is 3    
> This is 4    
> This is 5' | sed 'N;D'
This is 5

说明:

  • 读取This is 1,执行N,得出This is 1\nThis is 2\n,执行D。
  • 读取This is 3,执行N,得出This is 3\nThis is 4\n,执行D。
  • 读取This is 5,执行N,后续无内容,读取失败,放弃后续命令,正常打印This is 5

删除偶数行

bash 复制代码
[root@server ~ 18:53:55]# echo 'This is 1    
> This is 2    
> This is 3    
> This is 4    
> This is 5' | sed 'n;D'
This is 1    
This is 3    
This is 5

说明:

  • 读取This is 1,执行n,This is 2\n覆盖This is 1\n,执行D删除This is 2\n,This is 1\n没有删除,正常打印This is 1
  • 读取This is 3,执行n,This is 4\n覆盖This is 3\n,执行D删除This is 4\n,正常打印This is 3
  • 读取This is 5,执行n,后续无内容,读取失败,放弃后续命令,正常打印This is 5

打印行号

=====

bash 复制代码
[root@server ~ 18:55:12]# sed '=' test
1
root:x:0:0:root:/root:/bin/bash
2
......

#给 test 文件的每一行文本「添加行号」,行号和原文之间用冒号 : 分隔,最终输出 "行号:原文" 的格式
[root@server ~ 18:56:13]# sed '=' test|sed 'N;s/\n/:/'
1:root:x:0:0:root:/root:/bin/bash
......

大小写转换

y 字符

bash 复制代码
# 将小写字母s和i转换成大写字母S和I
[root@server ~ 18:59:40]# echo 'This is 1    
> This is 2    
> This is 3    
> This is 4    
> This is 5' | sed 'y/si/SI/'
ThIS IS 1    
ThIS IS 2    
ThIS IS 3    
ThIS IS 4    
ThIS IS 5

读取

bash 复制代码
#在 test 文件中所有「以 root 开头的行」的后面,插入 test2 文件的全部内容
[root@server ~ 19:06:02]# sed '/^root/r test2' test
root:x:0:0:root:/root:/bin/bash
=============
-------------
+++++++++++++

写入

w 写入

将模式空间中记录写入到文件中。

bash 复制代码
#将root开头的行,写入test3中
[root@server ~ 19:09:49]# sed '/^root/w test3' test
[root@server ~ 19:12:45]# cat test3
root:x:0:0:root:/root:/bin/bash
W 写入

将模式空间中第一条记录写入到文件中。

bash 复制代码
[root@server ~ 19:14:44]# cat scripts 
1{
N
w write.log
}
[root@server ~ 19:14:51]# sed -n -f scripts test
# 小写w写入包含模式中所有行
[root@server ~ 19:15:06]# cat write.log 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false

# 大写W写入只包含模式中第一行
[root@server ~ 19:16:30]# cat scripts 
1{
N
W write.log
}
[root@server ~ 19:16:37]# sed -n -f scripts test
[root@server ~ 19:16:41]# cat write.log 
root:x:0:0:root:/root:/bin/bash

更改

整行替换。

bash 复制代码
#root开头行替换出hello
[root@server ~ 19:16:47]# sed '/^root/chello' testhello
bin:x:1:1:bin:/bin:/bin/false

多命令执行 {} 和-f 选项

对匹配的内容执行多个命令。

bash 复制代码
#打印前两行
[root@server ~ 19:17:57]# echo 'This is 1    
> This is 2    
> This is 3' | sed -n '1{N;p}'
This is 1    
This is 2  

#只处理 test 文件第 1-5 行, 替换并打印
[root@server ~ 19:18:55]# sed -n '1,5{s/^root/hello/;p}' test
hello:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
mail:x:8:12:mail:/var/spool/mail:/bin/false
ftp:x:14:11:ftp:/home/ftp:/bin/false

 #多个命令写成脚本
[root@server ~ 19:14:44]# cat scripts 
1{
N
w write.log
}
#执行脚本
[root@server ~ 19:14:51]# sed -n -f scripts test

退出

bash 复制代码
#`2q`的意思是到第二行的时候,退出
[root@server ~ 19:20:14]# sed '2q' test
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false

! 匹配取反

表示后面的命令作用于所有没有被选定的行。

bash 复制代码
[root@server ~ 19:25:56]# sed -n '/^root/!p' test
bin:x:1:1:bin:/bin:/bin/false
.....
bash 复制代码
#`h`的作用是将找到的行,放到一个缓存区,`G` 的作用是将缓存区中的内容放到最后一行
[root@server ~ 19:26:22]# sed -e '/root/h' -e '$G' test
root:x:0:0:root:/root:/bin/bash
.....
ba:x:1002:1002::/home/zhangy:/bin/bash
test:x:1003:1003::/home/test:/bin/bash
@zhangying:*:1004:1004::/home/test:/bin/bash
policykit:x:102:1005:Po
root:x:0:0:root:/root:/bin/bash

#行替换,用匹配root的行,来替换匹配zhangy的行
[root@server ~ 19:26:22]# sed -e '/root/h' -e '$G' test
.....

.....

正则用法

  1. sed中正则表达式需要转移字符\,例如,用括号要加上 \ ,不然会报错。
  2. 使用 -r 选项不需要转义字符。
bash 复制代码
[root@server ~ 18:50:18]# cat test |sed -r 's/^root(.*)$//;/^$/d'
#或者
cat test |sed  's/^root\(.*\)$//;/^$/d'
  1. 子串使用
    • (),用于匹配子串
    • \N,N是个数字,代表前面匹配的第N个子串
    • &,代表匹配的所有内容
相关推荐
WangLanguager1 小时前
SVD介绍和代码示例
运维
柳鲲鹏1 小时前
LINUX下载编译libcamera
linux·运维·服务器
泡沫·1 小时前
2.grep使用手册
运维
天命码喽c1 小时前
Docker-compose部署GraphRAG-2.7.0
运维·docker·容器
init_23611 小时前
【BGP入门专题-5】bgp路由反射器RR
运维·网络
遇见火星1 小时前
Linux下挂载磁盘相关命令
linux·运维·服务器·磁盘·lsblk·fdisk
可爱又迷人的反派角色“yang”2 小时前
Mysql数据库(二)
运维·服务器·前端·数据库·mysql·nginx·云计算
小玉不愚鸭2 小时前
nginx中的https的搭建
运维·nginx·https
weixin_307779132 小时前
Jenkins ASM API 插件:详解与应用指南
java·运维·开发语言·后端·jenkins