shell三剑客_sed

蛋蛋 2022年09月13日 62 0

sed

sed 是Stream Editor(字符流编辑器)的缩写,简称流编辑器

Linux实战教学笔记12:linux三剑客之sed命令精讲

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

命令执行流程

image-20210528154355561

归纳流程

Sed软件从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行....

小知识:

一次一行的设计使得sed软件性能很高,sed在读取很是庞大的文件时不会出现卡顿的想象。你们都用过vi命令,用vi命令打开几十M或更大的文件,会发现有卡顿现象,这是由于vi命令打开文件是一次性将文件加载到内存,而后再打开,所以卡顿的时间长短就取决于从磁盘到内存的读取速度了。并且若是文件过大的话还会形成内存溢出现象。Sed软件就很好的避免了这种状况,打开速度很是快,执行速度也很快。

**详细流程:**缓存

现有一个文件person.txt,共有五行文本,sed命令读入文件person.txt的第一行“101,chensiqi,CEO”,并将这行文本存入模式空间(sed软件在内存中的一个临时缓存,用于存放读取到的内容,比喻为工厂流水线的传送带。)

文件person.txt在模式空间的完整处理流程

1,判断第1行是不是须要处理的行,若是不是要处理的行就从新从文件读取下一行,若是是要处理的行,则接着往下走。
2,对模式空间的内容执行sed命令,好比a(追加),i(插入),s(替换)...
3,将模式空间中通过sed命令处理后的内容输出到屏幕上,而后清空模式空间
4,读取下一行文本,而后从新执行上面的流程,直到文件结束

上面的流程归纳以下图所示

image-20210528155916218

选项说明

option[选项] 解释说明(带*的为重点)
-n 取消默认的sed软件的输出,常与sed命令的p连用。*
-e 一行命令语句能够执行多条sed命令
-f 选项后面能够接sed脚本的文件名
-r 使用扩展正则表达式,默认状况sed只识别基本正则表达式*
-i 直接修改文件内容,而不是输出到终端,若是不使用-i选项sed软件只是修改在内存中的数据,并不会影响磁盘上的文件*
sed -commands[sed命令] 解释说明(带*的为重点)
a 追加,在指定行后添加一行或多行文本*
c 取代指定的行
d 删除指定的行*
D 删除模式空间的部份内容,直到遇到换行符\n结束操做,与多行模式相关
i 插入,在指定行前添加一行或多行文本*
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命令*
{} 对单个地址或地址范围执行批量操做
+ 地址范围中用到的符号,作加法运算

sed入参、参数

只需要把sed后面的单引号换成双引号即可。

$cat a.txt
ds
%packages
%end
ds

$cat pkg.info
1
2
3

$sed -i '/%packages/r pkg.info' a.txt	#r读取pkg.info文件插入到%packages下一行
ds
%packages
1
2
3
%end
ds

追加

sed '1i 添加的内容' file    #这是在第一行(首行)前添加字符串
sed '$i 添加的内容' file    #这是在最后一行行前添加字符串
sed '$a添加的内容' file    #这是在最后一行行后(末尾)添加字符串
sed '1 a\string1\n\string2\n' /etc/passwd   #在第1行后插入两行字符串。
sed '1 i\string1\n\string2\n' /etc/passwd   #在第1行前插入两行字符串
# 注意这里的 " & " 符号,如果没有 “&”,就会直接将匹配到的字符串替换掉
sed 's/^/添加的头部&/g'      #在所有行首添加
sed 's/$/&添加的尾部/g'      #在所有行末添加
sed '2s/原字符串/替换字符串/g'  #替换第2行
sed '$s/原字符串/替换字符串/g' #替换最后一行
sed '2,5s/原字符串/替换字符串/g' #替换2到5行
sed '2,$s/原字符串/替换字符串/g' #替换2到最后一行

删除%packages之间%end的行

sed -i '/%packages/,/%end/{//!d}' a.txt

输出指定行

sed -n '4,/^$/p' a.txt		#输出第4行到最后一行
sed -n '4,/^$/!p' a.txt		#输出非第4行到最后一行,即1-3行

匹配字符之间,并输出指定行

cat test.log | sed -n '/|test.cn/,/##################/p'
2068|test.cn
      4 127.0.0.1:80
########################################################################

匹配多行并输出

sed  -n '/log_format/,/;/p' nginx.conf

特殊符号

&

&用于表示匹配到的结果。

sed '/source/s/^[^#].*/#&/' profile

圆括号

使用圆括号匹配的示例:(圆括号括起来的正则表达式所匹配的字符串会可以当成变量来使用,sed中使用的是1,2…)

sed 's/This is my \([^,&]*\),.*is \(.*\)/\1:\2/g' my.txt

BRE & ERE

反斜杠用于对字符串中特殊字符的转义。在使用圆括号时发现了一点疑问,网上给出的例子都需要对圆括号用\进行转义,而这不就是匹配圆括号本身吗?但是在实践中发现,确实当不用转义时会直接匹配字符,只有转义后才会体现括号的作用。

如:

# 
$ echo "()" | sed 's/()/a/g'
a

# 
$ echo "abc" | sed 's/\(b\)/\1\1/g'
abbc

而在之前学正则表达式的时候,是当需要匹配括号本身时才需要转义的。而这就是 基本正则表达式扩展正则表达式的区别了。

linux的文本处理命令中,grepsed都只支持基本正则,而egrepawk则支持扩展正则。但是grepsed也可以分别通过-E-r参数来支持扩展正则

基本正则

基本正则的元字符有以下:

1. ^
2. $
3. .
4. *
5. []
6. \<
7. \>
8. \(\)
9. \?
10.\+ 

网上很多博客把?+归为扩展正则,但是注意在基本正则中,是有这两个符号的,只是要通过转义来使用

在linux中测试可以发现这两个元字符都是可以正常使用的。
也有博客说|是扩展正则才有的

$ echo "ABC" | sed "s/A\+BC/DDD/"
DDD

$ echo "ABC" | sed "s/A\?BC/DDD/"
DDD

扩展正则

扩展正则只是把一些常用的元字符去掉了转义,并且加了少量新的元字符。

1. +
2. ?
3. ()

所以就明白了为什么在sed中的括号要进行转义了。因为sed使用的是基本正则,所以要想不用反斜杠直接使用括号,那么加上命令参数-r来让sed支持扩展正则就可以啦。对于grep是一样的道理,可以使用egrepgrep -E

报错

sed: -e expression #1, char 30: unterminated `s' command

网宿查了,反馈说是因为同一行里面有2个一样的字符串,命令不全,导致出现这个问题。

sed -i 's/2/88' 1.txt

解决方案,命令不全即可。

sed -i 's/2/88/' 1.txt

但是我写的命令命令不是这个问题

sed -i "s/^$domain\@.*$/&\@$customername/g" channel_file
Last Updated: 2024/03/20 11:02:12
shell语句_if linux基础命令_eval