1 什么是sed
sed是unix下的面向字符流的编辑器,即stream editor, 它是面向行的,以行为单位进行处理,同时,sed是非交互式的,一旦执行便要处理完整个文件。
sed起源于ed,而awk起源于sed和grep。
sed可以用来完成:
- 在一个或多个文件上自动实现编辑操作;
- 简化在多个文件执行相同的编辑处理工作;
- 编写文本转换工作;
sed的四种主要应用场景:
- 对同一文件进行多重编辑
- 改变一组文件
- 提取文件内容
- 编辑工作转移
2 sed的基本操作
2.1 命令格式
sed [options] script inputfile
常用选项:
-n
阻止输入行的自动输出。无该参数时,在脚本执行完成后,自动输出模式空间中的内容;
-f
指定脚本文件名
注意:
- 需要用大括号{}把过程括起来
- 需要用单引号''将指令括起来
- 需要用斜杠//将正则表达式括起来
2.2 模式空间和暂存空间
sed只读取输入文件的内容,但是并不改变文件中的内容,它通过维护一种模式空间,即一个工作区域或者叫做临时缓冲区,来放置从文件中读取的内容,并在模式空间中对内容进行编辑。
sed一次从文件中读取一行内容放入模式空间。这样做的好处是sed在读取非常大的文件时不会出现问题。
2.3 基本sed命令
注释
注释行的第一个字符必须是#
示例:
#这是一行sed注释
替换s
格式:
[address]s/pattern/replacement/flags
用途:
替换符合目标模式的的字符串
其中/
为定界符,当pattern中包含/
时,如果不想转义,可以使用其他字符如!
作为定界符来避免转义:s!/usr/mail!/usr2/mail!
flags的可选值有:
n
1-512之间的数字,表示对本模式中指定模式第n次出现的情况进行替换,
其中$
代表最后一行。
g
对模式空间的所有出现情况进行全局更改。
p
打印模式空间的内容。
w file
将模式空间的内容写入file
不指定flags时,默认flags为1,即替换第一次符合的情况。
flag可以组合使用,只要有意义就可以,如gp
表示对行进行全局替换并打印该行。
replacement是一个字符串,用来替换与正则表达式匹配的内容。在replacement部分,只有下列字符有特殊含义:
&
代表匹配的正在表达式的内容
\n
匹配第n个子串(n是一个数字),这个子串在pattern中用\(
和\)
指定。
\
转义字符
删除d
格式:
[address]d
用途:
删除符合匹配模式的字符串所在的整行,并重新读取下一行进入模式空间,将脚本执行流跳转到第一行,重新开始新一轮。
删除命令采用一个地址,如果行匹配这个地址就删除模式空间的内容。
删除命令还可是一个可以改变脚本中的控制流的命令。删除命令会导致读取新的输入行,并使脚本回到开头的第一行开始执行(即开始新一轮执行)
示例:
/^$/d
删除空行
/^$/!d
删除非空行
1d
删除第一行
$d
删除最后一行
追加、插入和更改
追加:
[line-address]a\
text
插入:
[line-address]i\
text
更改:
[line-address]c\
text
这些命令中的每一个都要求后面跟一个反斜杠\
用于转义第一个行尾。text
必须从下一行开始。要输入多行文本,每个连续的行都必须用反斜杠结束,最后一行例外。
替换y
格式:
[address] y /abc/xyz/
作用:
按位置将字符串abc中的每个字符,都转换成字符串xyz中的等价字符。
注意:y命令将影响整个模式空间的内容。
示例:
大小写转换:
y/abcdefghijk/ABCDEFGHIJK
打印p
格式:
p
作用:
输出模式空间的内容,它不会清空模式空间的内容也不会改变脚本的控制流。
示例:
在行改变前后打印之
/^\.Ah/{
p
s/"//g
s^\.Ah //p
}
注意:打印命令被提供给替换命令。替换命令的打印标志不同于打印命令,因为它是以成功的替换为条件的打印。
root$ ls
sedtxt txt
root$ cat txt
Hi
THis is a test file,
.Ah
haha this is end.
root$ cat sedtxt
/^\.Ah/{
p
s/"//g
s/^\.Ah //p
}
root$ sed -f sedtxt txt
Hi
THis is a test file,
.Ah
haha this is end.
打印行号=
格式:[line-address]=
作用:打印行号
示例:
root$ cat sedtxt
/^\.Ah/{
=
p
s/"//g
s/^\.Ah //p
}
root$ sed -nf sedtxt txt
4
.Ah
下一行n
格式:[address]n
作用:输出模式空间中的内容,然后读取输入的下一行,而不用返回到脚本的顶端。
示例:删除符合以.Ah
开始,且下一行为空行的模式中的空行
root$ cat nSed txt
/^\.Ah/{
n
/^$/d
}
Hi
THis is a test file,
.Ah
haha this is end.
root$ sed -f nSed txt
Hi
THis is a test file,
.Ah
haha this is end.
退出q
格式:[line-address]q
作用:停止读取新的输入行,脚本结束
示例:找到第一个Hi
找到第三行
root$ sed '/Hi/q' txt
Hi
root:sed fanshifeng$ sed '3q' txt
Hi
THis is a test file,
3 高级sed命令
高级命令分为3个组:
- 处理多行模式空间(N、D、P);
- 采用保持空间来保存模式空间的内容并使它可以用于后续的命令(H、h、G、g、x);
- 编写使用分支和条件指令的脚本来更改控制流(:、b、t);
3.1 多行模式空间
基本命令只能处理单个输入行的匹配,很难处理一个横跨了两行的匹配模式,为了解决这一问题,sed允许通过多行命令(N、D、P)来处理多行匹配的情况。使用这些命令可以创建出多行模式的空间。
在多行模式空间中,元字符^
匹配模式空间中的第一个字符,元字符$
匹配模式空间中的最后的换行符。
追加一行N
多行命令Next通过读取新的输入行,并将它追加到模式空间现有内容之后,两行之间以换行符分割,可以通过
\n
来匹配换行符。
N
与n
命令不同,next输出模式空间的内容,然后读取新的输入行。
$!N
对最后一行不执行Next命令,防止在奇数行时,出现最后一行无法输出的情况。
示例:将Owner and Operator Guide替换为Installation Guide
root$ cat NextSed txt
/Operator$/{
N
s/Owner and Operator\nGuide/Installation Guide/
}
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
root$ sed -f NextSed txt
Consult Section 3.1 in the Installation Guide for a description of the tape drives
available on your system.
这里有一个小问题,替换后的内容由两行变为了一行,我们再对它进行一些优化
root$ cat NextSed txt
/Operator$/{
N
s/Owner and Operator\nGuide/Installation Guide\
/
}
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
root$ sed -f NextSed txt
Consult Section 3.1 in the Installation Guide
for a description of the tape drives
available on your system.
多行删除D
作用:删除模式空间中直到第一个嵌入的换行符的这部分内容。它不会导致读入新的输入行,而且它会返回到脚本的顶端,重新开始执行脚本内容。
示例:删除多行空行,只保留一个空行
root$ cat txt
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.The Operator
The end!
root$ cat sedtxt
/^$/{
N
/^\n$/d
}
root$ cat sedtxt2
/^$/{
N
/^\n$/D
}
root$ sed -f sedtxt txt
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.The Operator
The end!
root$ sed -f sedtxt2 txt
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.The Operator
The end!
NOTE:利用了D命令只删除换行符前的内容而不是全部内容的特性。
多行打印P
作用:输出多行模式空间的第一部分,直到第一个嵌入的换行符为止。
重要:在执行完脚本的最后一个命令之后,模式空间的内容自动被输出,除非使用
-n
抑制这个动作。因此,当默认的输出被抑制或者脚本中的控制流被更改,以致不能到达脚本的底部时,需要使用打印命令P
或者p
。
Print命令经常出现在Next命令之后和Delete命令之前。这3个命令能建立一个输入/输出循环,用来维护两行的模式空间,但是一次只输出一行。这个循环的目的是只输出模式空间的第一行 ,然后返回到脚本的顶端将所有的命令应用于模式空间的第二行。
保持命令
H
:将模式空间的内容追加到保持空间
h
:将模式空间的内容复制到保持空间(替换掉原有内容)
G
:将保持空间的内容追加到模式空间
g
:将保持空间的内容复制到模式空间(替换掉原有内容)
x
:交换保持空间和模式空间的内容(替换掉原有内容)
示例:交换两行的位置
root$ cat num numSwap
1
2
3
4
5
6
/.*/{
h
N
s/.*\n//
G
}
root$ sed -f numSwap num
2
1
4
3
6
5
另一种方式:
root$ cat num numSwap
1
2
3
4
5
6
/.*/{
N
s/\(.*\)\n\(.*\)/\2\
\1/
}
root$ sed -f numSwap num
2
1
4
3
6
5
注意:这个替换命令
s/\(.*\)\n\(.*\)/\2\ \1/
匹配模式空间的2个部分,1)嵌入的换行符之前的所有字符,2)嵌入的换行符之后的素有内容。这个命令的替换部分回调被保存的部分,并按照不同的顺序重新组合他们,并通过换行符进行连接。
跳转命令b
格式:[address]b[label]
如果没有给出标签label,控制被转移到脚本的末尾。
标签格式::labelName
模式没有任何参数的跳转命令将跳至脚本末尾。
测试命令t
格式:[address]t[label]
用途:如果在当前匹配地址的行上进行了成功的替换,那么test命令就转到标签处。因此它隐含了一个条件分支。
如果没有给出标签label,控制被转移到脚本的末尾。
4 sed应用
使用sed模拟head
root$ cat num
1
2
3
4
5
6
root$ sed '5q' num
1
2
3
4
5
使用sed模拟tail
sed -e ':a' -e '$q;N;11,$D;ba' num
没看明白...
使用sed模拟两个模式的grep
root$ cat gredSed
#!/bin/bash
search=$1
shift
for file
do
sed '
/'"$search"'/b
N
h
s/.*\n//
/'"$search"'/b
g
s/ *\n/ /
/'"$search"'/{
g
b
}
g
D
' $file
done