三剑客之-sed

 
第一章 Sed 功能介绍、参数解释、增-删-改-查 测试


1、软件功能与版本


sed命令是操作、过滤和转换文本内容的强大工具、常用功能有增、删、改、查(增加、删除、修改、查询),其中查询的功能中最常用的2大功能是过滤(过滤指定字符),取行(取出指定行)。

[root@RedHat8-2 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux release 8.2 (Ootpa)

[root@RedHat8-2 ~]# sed --version
sed (GNU sed) 4.5
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Jay Fenlason, Tom Lord, Ken Pizzini,
and Paolo Bonzini.
GNU sed home page: <https://www.gnu.org/software/sed/>.
General help using GNU software: <https://www.gnu.org/gethelp/>.
E-mail bug reports to: <bug-sed@gnu.org>.

2、语法格式


sed  # stream editor 流编辑器 linux三剑客之一排行老二 擅长取行
语法:sed [OPTION]... {sed-dommands} [input-file]  /  sed [参数] ['内容'] file 
注意:
sed 以及后边选项、sed命令和输入文件,每个元素之间都至少有一个空格。
sed-commands既可以是单个sed命令,也可以是多个sed命令组合。
input-file(输入文件)是可选项,sed还能够从标准输入如管道获取输入

3、命令执行流程


概括流程:Sed软件从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行....
一次一行的设计使得sed软件性能很高,sed在读取非常庞大的文件时不会出现卡顿的现象。用vi命令打开几十M或更大的文件,会发现有卡顿现象,这是因为vi命令打开文件是一次性将文件加载到内存,然后再打开,因此卡顿的时间长短就取决于从磁盘到内存的读取速度了。而且如果文件过大的话还会造成内存溢出现象。sed软件就很好的避免了这种情况,打开速度非常快,执行速度也很快。

详细流程:现有一个文件test.txt,共有五行文本,sed命令读入文件test.txt的第一行“101,A”,并将这行文本存入模式空间(sed软件在内存中的一个临时缓存,用于存放读取到的内容,比喻为工厂流水线的传送带。)
文件test.txt在模式空间的完整处理流程:
(1)判断第1行是否是需要处理的行,如果不是要处理的行就重新从文件读取 下一行,如果是要处理的行,则接着往下走:
(2)对模式空间的内容执行sed命令,比如a(追加)、i(插入)、s(替换)......
(3)将模式空间中经过sed命令处理后的内容输出到屏幕上,然后清空模式空间:
(4)读取下一行文本,然后重新执行上面的流程,直到文件结束。

4、 选项说明:

option	解释说明(※)
-n	取消默认的sed软件的输出,常与sed命令的p连用※
-e	一行命令语句可以执行多条sed命令。
-f	选项后面可以接sed脚本的文件名。
-r	使用扩展正则表达式,默认情况sed只识别基本正则表达式。※
-i	直接修改文件内容,而不是输出到终端。如果不使用-i选项sed软件只是修改在内存中的数据,并不会影响磁盘上的文件。※

sed-commands{sed命令}	解释说明(※)
a	追加(append),在指定行后添加一行或多行文本。※
c	取代指定的行
d	删除指定的行※
D	删除模式空间的部分内容,直到遇到换行符\n结束操作,与多行模式相关。
i	插入(insert),在指定行前添加一行或多行文本。※
h	把模式空间的内容复制到保持空间。
H	把模式空间的内容追加到保持空间。
g	把保持空间的内容复制到模式空间。
G	把保持空间的内容追加到模式空间。
x	交换模式空间和保持空间的内容。
l	打印不可见的字符。
n	清空模式空间的内容并读入下一行。
N	不清空模式空间,并读取下一行数据并追加到模式空间。※
p	打印模式空间的内容,通常p会与选项-n一起使用。※
P(大写)	打印模式空间的内容,直到遇到换行符\n结束操作。
q	退出sed
r	从指定文件读取数据
s	取代,s#old#new#g==这里g是s命令的替代标志,注意和g命令区分※
w	另存,把模式空间的内容保存到文件中。
y	根据对应位置转换字符。
:label	定义一个标签。
b label	执行该标签后面的命令
t	如果前面的命令执行成功,那么就跳转到t指定的标签处,继续往下执行后续命令。否则,仍然继续正常的执行流程。

特殊符号	解释说明(※重点)
!	对指定行以外的所有行应用命令。※
=	打印当前行行号。※
~	“First~Step”表示从First行开始,以步长step递增。
&	代表被替换的内容。
;	实现一行命令语句可以执行多条sed命令。※
{}	对单个地址或地址范围进行批量操作。
+	地址范围中用到的符号,做加法运算。

5、 使用范例

5.1 测试文本

[root@RedHat8-2 ~]# cat test.txt
101,A
102,B
103,C
104,D
105,E

5.2 增

往文件指定位置追加或插入指定文本。
[root@RedHat8-2 ~]# cat test.txt
101,A
102,B
103,C
104,D
105,E

“a”(append):追加文本到指定行后,
[root@RedHat8-2 ~]# sed '1a 111,test' test.txt 
101,A
111,test
102,B
103,C
104,D
105,E

“i”(insert):插入文本到指定行前。
[root@RedHat8-2 ~]# sed '1i 111,test' test.txt
111,test
101,A
102,B
103,C
104,D
105,E

[root@RedHat8-2 ~]# sed '3i 111,test' test.txt
101,A
102,B
111,test
103,C
104,D
105,E

命令详解:
sed打头,然后接上空格(空格个数不限,但至少要有一个),在空格后面,我们先敲上一对单引号('')
(1)数字代表指定的对第几行记性操作,其他行忽略。
(2)i代表插入的意思,2i即在第2行前插入文本。
(3)2i后面加上空格,然后跟上你想要插入的文本即可。
     sed默认只是处理文件在内存中的数据及模式空间,并不会修改磁盘上的内容,想修改就需要另外一个sed选项“i”配合使用。
给文件第2行后添加2行空行。

[root@RedHat8-2 ~]# sed '2a \\n ' test.txt
101,A
102,B

 
103,C
104,D
105,E

给第2行后添加1个空行。
[root@RedHat8-2 ~]# sed '2a \\n ' test.txt
101,A
102,B

 
103,C
104,D
105,E

5.3 多行增加

特殊符号“\n”,换行符
[root@RedHat8-2 ~]# echo xhl;echo xhl
xhl
xhl
[root@RedHat8-2 ~]# echo -e "xhl\nxhl"
xhl
xhl
[root@RedHat8-2 ~]# cat test.txt
101,A
102,B
103,C
104,D
105,E
[root@RedHat8-2 ~]# sed '2a test1\ntest2' test.txt
101,A
102,B
test1
test2
103,C
104,D
105,E

5.4 删
删除文件中的某些行。
“d”:删除命令,记忆方法:d的全拼是delete,意思是删除。
指定执行的地址范围
sed软件可以对单行或多行文本进行处理,如果在sed命令前面不指定地址范围,那么默认会匹配所有行。
用法:n1[,n2] {sed-commands}
地址用逗号分隔开,n1,n2可以用数字、正则表达式、或者二者组合表示。

地址范围                        含义
10{sed-commands}               对第10行操作。
10,20{sed-commands}            对10到20行操作,包括第10,20行。
10,+20{sed-commands}           对10到30行{10+20}行操作,包括第10,30行。
1~2{sed-commands}              对1,3,5,7,..... 行操作。
10,$ {sed-commands}            对10到最后一行($代表最后一行)操作,包括第10行。
/xty/{sed-commands}            对匹配xty的行操作。
/xty/,/Dasha/{sed-commands}    对匹配xty的行到匹配Dasha的行操作。
/xty/,${sed-commands}          对匹配xty的行到最后一行操作。
/xty/,10{sed-commands}         对匹配xty的行到第10行操作,注意:如果前10行没有匹配到xty,sed软件会显示10行以后的匹配xty的行,如果有。
1,/Dasha/{sed-commands}        对第一行到匹配Dasha的行操作。
/xty/,+2{sed-commands}         对匹配xty的行到其后的2行操作。

sed命令前面不指定地址范围,默认会匹配所有行,然后使用d命令删除功能就会删除这个文件的所有内容。

[root@RedHat8-2 ~]# cat test.txt
101,A
102,B
test1
test2
103,C
104,D
105,E
[root@boyvm1 xty]# sed 'd' test.txt

执行删除第2行的文本,
[root@RedHat8-2 ~]# sed '2d' test.txt
101,A
103,C
104,D
105,E

[root@RedHat8-2 ~]# sed '2,5d' test.txt     删除2-5行
101,A
[root@RedHat8-2 ~]# sed '2d;5d' test.txt    删除2行到5行
101,A
103,C
104,D
[root@RedHat8-2 ~]# sed '/101/d' test.txt  删除匹配101的行
102,B
103,C
104,D
105,E
[root@RedHat8-2 ~]# sed '/101/,/104/d' test.txt   删除匹配101 到匹配104之间的行
105,E
[root@RedHat8-2 ~]# sed '1,/104/d' test.txt     删除1行到匹配104的行
105,E

5.5 特殊符号~(步长)解析
格式:“First~Step”表示从First行开始,以步长Step递增。这个在数学中叫等差数列。
例子:

1~2 匹配 1,3,5,7,.....    #用于只输出基数行
2~2 匹配 2,4,6,8......    #用于只输出偶数行
1~3 匹配 1,4,7,10....     #从1开始隔两个数字输出
2~3 匹配 2,5,8,11.....    #从2开始隔一个数字输出
[root@RedHat8-2 ~]# seq 1 3 10 ####命令说明:seq命令格式seq起始值 公差 结束值
1
4
7
10
[root@RedHat8-2 ~]# seq 10 | sed -n '1~3p' 
1
4
7
10
命令说明:"1~2"这是指定行数的另一种格式,从第一行开始以步长2递增的行(1,3,5),因此删掉第1,3,5行,即所有的奇数行。
[root@RedHat8-2 ~]# sed '1~2d' test.txt 
102,B
104,D

5.6 特殊符号!解析
感叹号“!”,取反的意思。
命令说明:在地址范围"2,3"后边加上“!”,如果不加"!"表示删除第2行和第3行,结果如下面的例子所示,然后加上“!”的结果就是除了第2行和第3行以外的内容都删除。
[root@RedHat8-2 ~]# sed '2,3!d' test.txt 
102,B
103,C

5.7 改
(1)按行替换

“c”:用新行取代旧行,记忆方法:c(change),意思是替换。
命令说明:使用sed命令c将原来第2行“102,zhang,CTO”替换成“xhl”,整行替换。
[root@RedHat8-2 ~]# cat test.txt 
101,A
102,B
103,C
104,D
105,E
[root@RedHat8-2 ~]# sed '2c test4 ' test.txt 
101,A
test4 
103,C
104,D
105,E

(2)文本替换

“s”:单独使用->将每一行中第一处匹配的字符串进行替换===>sed命令。
“g” :每一行进行全部替换-->sed命令s的替换标志之一(全局替换),非sed命令。
“i” :修改文件内容->sed的选项,注意和sed命令i区分。    
sed软件替换模型(方框■被替换成三角▲)
sed -i 's/■/▲/g' test2.log
sed -i 's#■#▲#g' test2.log

1)两边是引号,引号里面的两边分别为s和g,中间是三个一样的字符/或#作为定界符。#常用,如替换注释类文本可用/或其他定界符代替。
2)定界符/或#,第一个和第二个之间的就是被替换的内容,第二个和第三个之间的就是替换后的内容。
3)'s#■#▲#g' xty.log,■能用正则表达式,但▲不能用,必须是具体的,因为▲使用正则的话会让sed软件无所适从。它不知道你要替换什么内容。
4)默认sed软件是对模式空间(内存中的数据)操作,而-i选项会更改磁盘上的文件内容。

[root@RedHat8-2 ~]# cat 123 
xhl
mm
test
[root@RedHat8-2 ~]# sed  -i  's#test#ceshi#g' 123 
[root@RedHat8-2 ~]# cat 123 
xhl
mm
ceshi


将需要替换的文本“test”放在第一个和第二个“#”之间,将替换后的文本“ceshi”放在第二个和第三个“#”之间。

5.8 指定行修改配置文件

[root@RedHat8-2 ~]# cat 123 
xhl
mm
ceshi
[root@RedHat8-2 ~]# sed '1s#xhl#1#' 123 
1
mm
ceshi

sed命令“s”前没有指定地址范围,默认是对所有行进行操作。sed“s” 前加数字就代表对该行进行操作。

5.9 变量替换
变量替换就是将文本变成了变量进行替换。

[root@RedHat8-2 ~]# cat test.txt
101,A
102,B
103,C
104,D
105,E
[root@RedHat8-2 ~]# x='101,A'
[root@RedHat8-2 ~]# y='b'
[root@RedHat8-2 ~]# echo $x $y
101,A b
[root@RedHat8-2 ~]# sed "s#$x#$y#g" test.txt
b
102,B
103,C
104,D
105,E

5.10 分组替换(后向引用)
sed的\(\)的功能可以记住正则表达式的一部分,其中\1位第一个记住的模式即第一个小括号中的匹配内容,\2第二记住的模式,即第二个小括号中的匹配内容,sed最多可以记住9个。

[root@RedHat8-2 ~]# echo "I am xty I am a superman" |sed -r 's#^.*am (.*) I.*$#\1#g'
xty

sed 's#\(.*\)#\1#g'
sed -r 's#(.*)#\1#g'

不使用“-r”选项就使用转义字符号“\”(sed 不加-r 不支持扩张正则表达式),使用“-r”选项就可以直接使用“()”

执行命令取出eth0的ip地址

[root@RedHat8-2 ~]# ifconfig ens32 | sed -nr '2s#^.*net (.*) netmask.*$#\1#gp'
172.20.10.6 

5.11 批量重命名文件
5.11.1 批量创建测试文件

[root@RedHat8-2 ~]# pwd
/root
[root@RedHat8-2 ~]# mkdir test
[root@RedHat8-2 ~]# cd test
[root@RedHat8-2 test]# echo test_210530_{01..10}.txt|xargs -n1|awk '{print "touch",$1}'|bash
[root@RedHat8-2 test]# ll
total 0
-rw-r--r-- 1 root root 0 May 30 23:33 test_210530_01.txt
-rw-r--r-- 1 root root 0 May 30 23:33 test_210530_02.txt
-rw-r--r-- 1 root root 0 May 30 23:33 test_210530_03.txt
-rw-r--r-- 1 root root 0 May 30 23:33 test_210530_04.txt
-rw-r--r-- 1 root root 0 May 30 23:33 test_210530_05.txt
-rw-r--r-- 1 root root 0 May 30 23:33 test_210530_06.txt
-rw-r--r-- 1 root root 0 May 30 23:33 test_210530_07.txt
-rw-r--r-- 1 root root 0 May 30 23:33 test_210530_08.txt
-rw-r--r-- 1 root root 0 May 30 23:33 test_210530_09.txt
-rw-r--r-- 1 root root 0 May 30 23:33 test_210530_10.txt

5.11.2 批量重命名文件

[root@RedHat8-2 test]# ls |sed -r 's#(^.*)_210530(.*$)#mv & \1\2#'
mv test_210530_01.txt test_01.txt
mv test_210530_02.txt test_02.txt
mv test_210530_03.txt test_03.txt
mv test_210530_04.txt test_04.txt
mv test_210530_05.txt test_05.txt
mv test_210530_06.txt test_06.txt
mv test_210530_07.txt test_07.txt
mv test_210530_08.txt test_08.txt
mv test_210530_09.txt test_09.txt
mv test_210530_10.txt test_10.txt

5.11.3 批量重命名命令说明
(1)“\1”代表前面“(^.*)”匹配的内容,“&”代表“s# #”里被替换的内容,这里匹配到的是完整的文件名。
(2)使用bash命令执行,bash命名执行标准输入的语句,等同在命令行输入语句后敲回车。
ls |sed -r 's#(^.*)_210530(.*$)#mv & \1\2#'|bash

[root@RedHat8-2 test]# ls
test_01.txt  test_02.txt  test_03.txt  test_04.txt  test_05.txt  test_06.txt  test_07.txt  test_08.txt  test_09.txt  test_10.txt

5.12 查
“p”:输出指定内容,但默认会输出2次匹配的结果,因此使用-n选项取消默认输出,p的全拼是print(打印

[root@RedHat8-2 ~]# sed -nr '/A|B/p' test.txt 
101,A
102,B

[root@RedHat8-2 ~]# sed -nr '/A/,/D/p' test.txt  #打印A到D之间的行包含A、D行
101,A
102,B
103,C
104,D

[root@RedHat8-2 ~]# sed -n '/C/,1p' test.txt
103,C


特殊情况:前两行没有匹配到C,就向后匹配,如果匹配到C就打印此行,匹配到文件结尾


第二章 进阶功能(修改、替换、精确匹配、=)

2.1 修改文件


真正修改文件内容需要使用-i选项,修改时需要提前备份,sed -i选项自带备份功能
-i [SUFFIX], --in-place[=SUFFIX]
-i [备份文件后缀], --in-place[=本分文件后缀]
测试文件内容:

[root@RedHat8-2 ~]# cat test.txt
101,A
102,B
103,C
104,D
105,E

备份并替换

[root@RedHat8-2 ~]# sed -i.bak 's#E#F#g' test.txt 
[root@RedHat8-2 ~]# ls
test.txt  test.txt.bak
[root@RedHat8-2 ~]# cat test.txt
101,A
102,B
103,C
104,D
105,F

2.2 sed替换命令Ms# # #Ng 的使用


  语法说明:
Ms---对第M行处理,无g替换标志,只处理第一处匹配,有g标志则对第M行全部替换。
Ng---对每一行,从第N处开始替换。
Ms、Ng合用表示只对第M行从第N处匹配开始替换。

cat >num.txt <<EOF
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
EOF
[root@RedHat8-2 ~]# sed '1s#1#0#2g' num.txt 
1 0 0 0 0
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
[root@RedHat8-2 ~]# sed '1s#1#0#2' num.txt 
1 0 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
[root@RedHat8-2 ~]# sed '1s#1#0#g' num.txt 
0 0 0 0 0
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

2.3 数字标志


数字标志,s# # #N,注意N后边没有g。表示替换每行中第N次出现的匹配项,属于精确匹配,N的取值范围1<N<512

[root@RedHat8-2 ~]# sed '2s#1#0#2' num.txt 
1 1 1 1 1
1 0 1 1 1
1 1 1 1 1
1 1 1 1 1

2.4 特殊符号=获取行号


如何获取一个文件的行号

[root@RedHat8-2 ~]# sed "=" test.txt     ##“=”可以获取行号,缺点行号和行不在一行
1
101,A
2
102,B
3
103,C
4
104,D
5
105,F
  
[root@RedHat8-2 ~]# sed "1,3=" test.txt   #显示第一行到第3行号
1
101,A
2
102,B
3
103,C
104,D
105,F

[root@RedHat8-2 ~]# sed -n "$=" test.txt   #只显示行号但不显示行的内容,取消默认输出
5


"$”代表最后一行,因此显示最后一行的行号,变相得出文件的总行数。

改进方法

[root@RedHat8-2 ~]# sed "=" test.txt  | sed 'N;s#\n# #g'
1 101,A
2 102,B
3 103,C
4 104,D
5 105,F

2.5 分号;的使用


第2种方法使用;(分号)也可以执行多条命令。
正常执行命令

[root@RedHat8-2 ~]# mkdir test
[root@RedHat8-2 ~]# cd test
[root@RedHat8-2 test]# pwd
/root/test


简化流程

[root@RedHat8-2 ~]# mkdir test;cd test
[root@boyvm1 test]# pwd
/root/test

sed测试

[root@RedHat8-2 ~]# sed '3,$d;s#10#01#' test.txt
011,A
012,B

2.6 选项-f


第3种方法使用-f选项接sed脚本。把多个sed命令合并到一个文件中,这个文件被称为sed脚本,然后就使用-f选项调用它。

[root@RedHat8-2 ~]# cat test.sed 
3,$d
s#10#01#
[root@RedHat8-2 ~]# sed -f test.sed test.txt
011,A
012,B

命令说明:使用sed选项-f接sed脚本test.sed。

案例:一个文件100行,把5,35,70行单独拿出来

[root@RedHat8-2 ~]# sed -n '5p;35p;70p' /etc/services
# IANA services version: last updated 2016-07-08
qotd            17/tcp          quote
bootps          67/udp

awk取行

[root@RedHat8-2 ~]# awk 'NR==5|| NR==35||NR==70{print $0}' /etc/services
# IANA services version: last updated 2016-07-08
qotd            17/tcp          quote
bootps          67/udp

2.7 特殊符号{}的使用


  {commands}可以把多个命令括起来,用来处理单个地址或者地址范围。

打印文件的第2到4行,并只显示这三行的行号

[root@RedHat8-2 ~]# sed -n '2,4p' test.txt
102,B
103,C
104,D

打印第2到4行

[root@RedHat8-2 ~]# sed -n '2,4p;=' test.txt
1
102,B
2
103,C
3
104,D
4
5

案例:svn账号密码

[root@RedHat8-2 ~]# cat svn.txt 
st210503
slfjdlsf
stu10312
sfls0ewe
[root@RedHat8-2 ~]# sed 'N;s#\n#=#' svn.txt 
st210503=slfjdlsf
stu10312=sfls0ewe

awk将换行\n替换方法

[root@RedHat8-2 ~]# awk '{printf "%s=", $0;getline ;print}' svn.txt 
st210503=slfjdlsf


stu10312=sfls0ewe命令详解
(1)printf 与print的区别;默认情况printf不会自动添加换行符,需手动添加。

[root@RedHat8-2 ~]# awk '{print $0}' svn.txt 
st210503
slfjdlsf
stu10312
sfls0ewe

[root@RedHat8-2 ~]# awk '{printf $0}' svn.txt 
st210503slfjdlsfstu10312sfls0ewe

把\n替换成=

[root@RedHat8-2 ~]# awk '{printf "%s=", $0}' svn.txt 
st210503=slfjdlsf=stu10312=sfls0ewe=

(2)getline的功能,读入下一行的输入赋予$0
==printf"%s=",$0
结果:st210503=(不换行)
==getline;print  $0
结果:$0为slfjdlsf
拼起来
st210503=slfjdlsf(print自动换行)

[root@RedHat8-2 ~]# awk '{printf $0 "%s="  ,getline;print}' svn.txt 
st210503=slfjdlsf
stu10312=sfls0ewe

2.8 操作多个文件


sed可以同时对多个文件处理。

[root@RedHat8-2 ~]# sed -n  '/root/p' /etc/passwd /etc/group
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
root:x:0:

2.8.1 合并两个文件(模拟cat)

[root@RedHat8-2 ~]# sed '' test.txt svn.txt 
101,A
102,B
103,C
104,D
105,F
st210503
slfjdlsf
stu10312
sfls0ewe
[root@RedHat8-2 ~]# sed '$r svn.txt' test.txt
101,A
102,B
103,C
104,D
105,F
st210503
slfjdlsf
stu10312
sfls0ewe
[root@RedHat8-2 ~]# sed '$r test.txt' svn.txt 
st210503
slfjdlsf
stu10312
sfls0ewe
101,A
102,B
103,C
104,D
105,F

2.8.2 模拟head命令

[root@RedHat8-2 ~]# sed  '3,$d' test.txt
101,A
102,B
[root@RedHat8-2 ~]# sed -n '3,$p' test.txt
103,C
104,D
105,F
[root@RedHat8-2 ~]# sed '2q' test.txt
101,A
102,B

2.8.3 模拟wc命令
 

[root@RedHat8-2 ~]# sed -n '$=' test.txt
5 

 

posted @ 2021-06-01 00:46  -小-白-  阅读(163)  评论(0编辑  收藏  举报