Shell 四剑客之 sed s替换内容以及n p

SED命令详解
本文深入解析SED流编辑器的使用方法,包括行寻址、替换脚本命令、多行处理及文本模式匹配技巧,帮助读者掌握高级文本编辑技能。

Vim 采用的是交互式文本编辑模式,你可以用键盘命令来交互性地插入、删除或替换数据中的文本。但 sed 命令不同,它采用的是流编辑模式,最明显的特点是,在 sed 处理数据之前,需要预先提供一组规则,sed 会按照此规则来编辑数据。

sed 会根据脚本命令来处理文本文件中的数据,这些命令要么从命令行中输入,要么存储在一个文本文件中,此命令执行数据的顺序如下:

  1. 每次仅读取一行内容;
  2. 根据提供的规则命令匹配并修改数据。注意,sed 默认不会直接修改源文件数据,而是会将数据复制到缓冲区中,修改也仅限于缓冲区中的数据;
  3. 将执行结果输出。

当一行数据匹配完成后,它会继续读取下一行数据,并重复这个过程,直到将文件中所有数据处理完毕。
 sed 命令的基本格式如下:

[root@localhost ~]# sed [选项] [脚本命令] 文件名

该命令常用的选项及含义,如表所示:

sed 命令常用选项及含义
选项含义
-e 脚本命令该选项会将其后跟的脚本命令添加到已有的命令中。
-f 脚本命令文件该选项会将其后文件中的脚本命令添加到已有的命令中。
-n默认情况下,sed 会在所有的脚本指定执行完毕后,会自动输出处理后的内容,而该选项会屏蔽启动输出,需使用 print 命令来完成输出。
-i此选项会直接修改源文件,要慎用。

 成功使用 sed 命令的关键在于掌握各式各样的脚本命令及格式,它能帮你定制编辑文件的规则。

 

使用数字方式进行行 寻址


sed 编辑器将文本流中的每一行都进行编号,第一行的编号为 1,后面的按顺序分配行号。通过指定特定的行号,可以选择编辑特定的行。举几个例子:

[root@bogon ~]# sed '3 s/bin/BIN/g' /etc/passwd     #将第 3 行中所有的 bin 替换成 BIN

[root@bogon ~]# sed '2,5 s/bin/BIN/g' /etc/passwd   #将第 2 行到 5行所有的 bin 替换成 BIN

[root@bogon ~]# sed '10,$ s/bin/BIN/g' /etc/passwd  #将第10行到最后一行中所有 bin 替换成 BIN

注:行寻址不止对替换命令有效,对其他目录也都是有效的,后面也会用到。

 

 

sed s 替换脚本命令


此命令的基本格式为:

s/pattern/replacement/flags

其中,address 表示指定要操作的具体行,pattern 指的是需要替换的内容,replacement 指的是要替换的新内容。

此命令中常用的 flags 标记如表所示:

sed s命令flags标记及功能
flags 标记功能
n1~512 之间的数字,表示指定要替换的字符串出现第几次时才进行替换,例如,一行中有 3 个 A,但用户只想替换第二个 A,这是就用到这个标记;
g对数据中所有匹配到的内容进行替换,如果没有 g,则只会在第一次匹配成功时做替换操作。例如,一行数据中有 3 个 A,则只会替换第一个 A;
p会打印与替换命令中指定的模式匹配的行。此标记通常与 -n 选项一起使用。
w file将缓冲区中的内容写到指定的 file 文件中;
&用正则表达式匹配的内容进行替换;
\n匹配第 n 个子串,该子串之前在 pattern 中用 \(\) 指定。
\转义(转义替换部分包含:&、\ 等)。

sed替换内容实战


flags参数使用,表示指定要替换的字符串出现第几次时才进行替换

[root@localhost ~]# sed 's/test/trial/2' data4.txt
This is a test of the trial script.
This is the second test of the trial script.
可以看到,使用数字 2 作为标记的结果就是,sed 编辑器只替换每行中第 2 次出现的匹配模式。

如果要用新文件替换所有匹配的字符串,可以使用 g 标记:
[root@localhost ~]# sed 's/test/trial/g' data4.txt
This is a trial of the trial script.
This is the second trial of the trial script.

提供ns来指定替换文本第几行的关键字内容 和 -e来将其后跟的脚本命令添加到已有的命令中

[root@www ~]# cat sed.txt 
123
qfq
root
root
root
qwf
ok
This is a test of the trial script.
This is the second test of the trial script.

[root@www ~]# sed -e "1s/123/456/g" -e "3s/root/linux/g" sed.txt --使用-e和下面使用;号等价
456
qfq
linux
root
root
qwf
ok
This is a test of the trial script.
This is the second test of the trial script.

[root@www ~]# sed -e "1s/123/456/g;3s/root/linux/g" sed.txt   
456
qfq
linux
root
root
qwf
ok
This is a test of the trial script.
This is the second test of the trial script.

sed N使用

[root@www ~]# cat list.txt 
192.168.179.99
192.168.179.100
192.168.179.101
192.168.179.102


#sed以行为单位处理文本,其模式缓冲区内只保留一行内容待处理。
N命令,将下一行读入并附加到当前行后面,以\n(换行符)分隔,一起存在模式缓冲区内
\n 就表示换行符

[root@www ~]# sed 'N;s/\n//g' list.txt    -N表示开启多行处理,一次处理两行即将两行一次性读取到内存当中,并且将两行之间的换行符去掉
192.168.179.99192.168.179.100
192.168.179.101192.168.179.102

[root@www ~]# sed 'N;N;s/\n//g' list.txt  --以后每次多一个N就是多一行合并处理 
192.168.179.99192.168.179.100192.168.179.101
192.168.179.102


[root@www ~]# sed = list.txt 
1
192.168.179.99
2
192.168.179.100
3
192.168.179.101
4
192.168.179.102

[root@www ~]# sed = list.txt  | sed 'N;s/\n/)/g'  --和上面一样一次处理两行将换行符换为)
1)192.168.179.99
2)192.168.179.100
3)192.168.179.101
4)192.168.179.102

sed在某行前面后面添加内容(//是先匹配某行,然后再去修改替换)

[root@www ~]# cat sed.sh   
192.168.179.1.15
192.168.179.1.16
192.168.179.1.17
[root@www ~]# sed '/192.168.179.1.15/s/^/---/g' sed.sh   --在某一行前面添加----
---192.168.179.1.15
192.168.179.1.16
192.168.179.1.17


[root@www ~]# sed '/192.168.179.99/s/$/----/g' list.txt   --在某一行末尾添加----
192.168.179.99----
192.168.179.100
192.168.179.101
192.168.179.102

[root@www ~]# cat list.txt 
192.168.179.99
192.168.179.100
192.168.179.101
192.168.179.102
[root@www ~]# sed '/192.168.179.99/s/99/999/g' list.txt   --先匹配到某一行,再使用s替换
192.168.179.999
192.168.179.100
192.168.179.101
192.168.179.102



[root@www ~]# sed -e '/192.168.179.99/s/^/---/g' -e '/192.168.179.99/s/$/---/g' list.txt  --前面后面都添加---
---192.168.179.99---
192.168.179.100
192.168.179.101
192.168.179.102



[root@www ~]# sed -e 's/^/---/g' -e 's/$/---/g' list.txt   --在所有的行前后添加信息
---192.168.179.99---
---192.168.179.100---
---192.168.179.101---
---192.168.179.102---


[root@www ~]# sed '/100/,/101/s/^/test/g' list.txt   --在100-101行之间前面添加test
192.168.179.99
test192.168.179.100
test192.168.179.101
192.168.179.102



[root@www ~]# nl /etc/passwd | head -n 5
     1	root:x:0:0:root:/root:/bin/bash
     2	bin:x:1:1:bin:/bin:/sbin/nologin
     3	daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4	adm:x:3:4:adm:/var/adm:/sbin/nologin
     5	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@www ~]# nl /etc/passwd | sed 's/^[[:space:]]*//g' | head -n 5   将前面的空格缩进
1	root:x:0:0:root:/root:/bin/bash
2	bin:x:1:1:bin:/bin:/sbin/nologin
3	daemon:x:2:2:daemon:/sbin:/sbin/nologin
4	adm:x:3:4:adm:/var/adm:/sbin/nologin
5	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

[root@www ~]# nl /etc/passwd | sed 's/^[[:space:]]*//g' | sed 's/\t/)/g' | head -n 5
1)root:x:0:0:root:/root:/bin/bash
2)bin:x:1:1:bin:/bin:/sbin/nologin
3)daemon:x:2:2:daemon:/sbin:/sbin/nologin
4)adm:x:3:4:adm:/var/adm:/sbin/nologin
5)lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@www ~]# nl /etc/passwd | sed 's/^[[:space:]]*//g' | sed 's/\t/)/g' |  sed 's/$/./g'
| head -n 5 
1)root:x:0:0:root:/root:/bin/bash.
2)bin:x:1:1:bin:/bin:/sbin/nologin.
3)daemon:x:2:2:daemon:/sbin:/sbin/nologin.
4)adm:x:3:4:adm:/var/adm:/sbin/nologin.
5)lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin.


[root@www ~]# nl /etc/passwd | sed 's/^ *//g' | sed 's/\t/)/g' | sed 's/$/./g' | head -n 5
1)root:x:0:0:root:/root:/bin/bash.
2)bin:x:1:1:bin:/bin:/sbin/nologin.
3)daemon:x:2:2:daemon:/sbin:/sbin/nologin.
4)adm:x:3:4:adm:/var/adm:/sbin/nologin.
5)lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin.
​

sed n p(一般和sed s替换一起使用 sed -n 's/pattern/replacement/p')


我们知道,-n 选项会禁止 sed 输出,但 p 标记会输出修改过的行,将二者匹配使用的效果就是只输出被替换命令修改过的行,例如:

[root@localhost ~]# cat data5.txt
This is a test line.
This is a different line.
[root@localhost ~]# sed -n 's/test/trial/p' data5.txt
This is a trial line.


[root@www ~]# sed -n '/nginx/p' /usr/local/nginx/conf/nginx.conf
user  nginx;
pid        logs/nginx.pid;
[root@www ~]# sed -n 's/nginx/test/p' /usr/local/nginx/conf/nginx.conf
user  test;
pid        logs/test.pid;

打印匹配区间范围的行(要匹配范围使用"/xxx/,/xxx/")

[root@www ~]# sed -e '/#/d' -e '/^$/d'  -e  '/server/,$d' nginx.conf | sed -n '/events/,/http/p'
events {
    worker_connections  1024;
}
http {

 下面再随便举几个例子:

数据的搜寻并显示

搜索 /etc/passwd有root关键字的行

nl /etc/passwd | sed '/root/p'
1  root:x:0:0:root:/root:/bin/bash
2  daemon:x:1:1:daemon:/usr/sbin:/bin/sh
3  bin:x:2:2:bin:/bin:/bin/sh
4  sys:x:3:3:sys:/dev:/bin/sh
5  sync:x:4:65534:sync:/bin:/bin/sync
....下面忽略

如果root找到,除了输出所有行,还会输出匹配行。使用-n的时候将只打印包含模板的行。

nl /etc/passwd | sed -n '/root/p'
1  root:x:0:0:root:/root:/bin/bash
[root@www ~]# cat sed.txt 
123
qfq
root
root
root
qwf
ok
This is a test of the trial script.
This is the second test of the trial script.

[root@www ~]# sed   "/root/p"sed.txt 
123
qfq
root
root
root
root
root
root
qwf
ok
This is a test of the trial script.
This is the second test of the trial script.

[root@www ~]# sed -n  "/root/p" sed.txt  --查找某一行的关键字使用-n p选项,n是静默,p是打印
root
root
root

[root@www ~]# sed -n 's/disabled/enforcing/p' /etc/selinux/config 
#     enforcing - No SELinux policy is loaded.
SELINUX=enforcing

[root@www ~]# sed -n "/qwf/"p sed.txt   --查看某一行的信息
qwf
[root@www ~]# sed -n "1p" sed.txt 
123
[root@www ~]# sed -n "2p" sed.txt 
qfq

[root@www ~]# sed -n "1,2p" sed.txt   --查看1-2行 
123
qfq
[root@www ~]# sed -n "1p;3p" sed.txt  --查看第1行第3行
123
root
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值