sed
sed 是Stream Editor(字符流编辑器)的缩写,简称流编辑器
Linux实战教学笔记12:linux三剑客之sed命令精讲
- Sed命令是操做,过滤和转换文本内容的强大工具。经常使用功能有增删改查(增长,删除,修改,查询),其中查询的功能中最经常使用的2大功能是过滤(过滤指定字符串),取行(取出指定行)。
命令执行流程

归纳流程:
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,读取下一行文本,而后从新执行上面的流程,直到文件结束
上面的流程归纳以下图所示:

选项说明
| 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的文本处理命令中,grep和sed都只支持基本正则,而egrep和awk则支持扩展正则。但是grep和sed也可以分别通过-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是一样的道理,可以使用egrep或grep -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