语法:
sed [ -n ] 'command' [ file ... ]
sed [ -n ] -e ‘command’ ... [ file ... ]
sed [ -n ] -f script-file ... [ file ... ]
sed命令
命令 | 功能 |
a\ | 在当前行后添加一行或多行。多行时除最后一行外,每行末尾需用“\”续行 |
c\ | 用此符号后的新文本替换当前行中的文本。多行时除最后一行外,每行末尾需用"\"续行 |
i\ | 在当前行之前插入文本。多行时除最后一行外,每行末尾需用"\"续行 |
d | 删除行 |
h | 把模式空间里的内容复制到暂存缓冲区 |
H | 把模式空间里的内容追加到暂存缓冲区 |
g | 把暂存缓冲区里的内容复制到模式空间,覆盖原有的内容 |
G | 把暂存缓冲区的内容追加到模式空间里,追加在原有内容的后面 |
l | 列出非打印字符 |
p | 打印行 |
n | 读入下一输入行,并从下一条命令而不是第一条命令开始对其的处理 |
q | 结束或退出sed |
r | 从文件中读取输入行 |
! | 对所选行以外的所有行应用命令 |
s | 用一个字符串替换另一个 |
g | 在行内进行全局替换 |
w | 将所选的行写入文件 |
x | 交换暂存缓冲区与模式空间的内容 |
y | 将字符替换为另一字符(不能对正则表达式使用y命令) |
sed选项
选项 | 功能 |
-e | 进行多项编辑,即对输入行应用多条sed命令时使用 |
-n | 取消默认的输出 |
-f | 指定sed脚本的文件名 |
元字符 | 功能 | 示例 |
^ | 行首定位符 | /^my/ 匹配所有以my开头的行 |
$ | 行尾定位符 | /my$/ 匹配所有以my结尾的行 |
. | 匹配除换行符以外的单个字符 | /m..y/ 匹配包含字母m,后跟两个任意字符,再跟字母y的行 |
* | 匹配零个或多个前导字符 | /my*/ 匹配包含字母m,后跟零个或多个y字母的行 |
[] | 匹配指定字符组内的任一字符 | /[Mm]y/ 匹配包含My或my的行 |
[^] | 匹配不在指定字符组内的任一字符 | /[^Mm]y/ 匹配包含y,但y之前的那个字符不是M或m的行 |
\(..\) | 保存已匹配的字符 | 1,20s/\(you\)self/\1r/ 标记元字符之间的模式,并将其保存为标签1,之后可以使用\1来引用它。最多可以定义9个标签,从左边开始编号,最左边的是第一个。此例中,对第1到第20行进行处理,you被保存为标签1,如果发现youself,则替换为your。 |
& | 保存查找串以便在替换串中引用 | s/my/**&**/ 符号&代表查找串。my将被替换为**my** |
\< | 词首定位符 | /\<my/ 匹配包含以my开头的单词的行 |
\> | 词尾定位符 | /my\>/ 匹配包含以my结尾的单词的行 |
x\{m\} | 连续m个x | /9\{5\}/ 匹配包含连续5个9的行 |
x\{m,\} | 至少m个x | /9\{5,\}/ 匹配包含至少连续5个9的行 |
x\{m,n\} | 至少m个,但不超过n个x | /9\{5,7\}/ 匹配包含连续5到7个9的行 |
s命令里以g结尾表示:替代文本取代正则表达式中的每一个匹配的。如果没有设置g,sed就会取代第一个匹配的。
鲜为人知的是:你可以在结尾指定数字,指示第n个匹配出现才要被取代:
$echo Tolstoy reads well. Tolstoy writes well. > example.txt
$sed 's/Tolstoy/Camus/2' < example.txt
Tolstoy reads well. Camus writes well.
POSIX允许使用分号将同一行里的不同命令隔开:
sed 's/foo/bar/g ; s/chicken/cow/g' myfile > myfile2
不过许多商用sed版本可能不支持此用法。
ed与其先驱ex和vi一样,sed会记得在脚本里遇到的最后一个正则表达式——不管它在哪里。
s/foo/bar/3 替换第三个foo
s//quux/ 替换第一个foo
sed运行方式:
sed读取每一个文件,一次读一行,将读取的行放在内存的一个区域——称之为模式空间(pattern space)。这就像程序语言里的变量一样:内存的一个区域在编辑命令的指示下可以修改,所有编辑上的操作都会应用到模式空间的内容。当所有操作完成后,sed会将模式空间的最后内容打印到标准输出,再回到开始处,读取另一个输入行。
匹配特定行:
sed默认是将每一个编辑命令用用到每一个输入行。但是,其实它是可以定值的。即,限制一条命令要用到那些行,只要在命令前置一个地址即可。所以sed 命令的完成形式就是:
address command
以下为不同种类的地址:
正则表达式
将以模式放置到一条命令之前,可限制命令应用于匹配模式的行。可与s命令搭配使用:
/oldfunc/ s/$/# XXX: migrate to newfunc/
s命令里的空模式指的是“使用前一个正则表达式”
行编号
可以使用绝对的行编号作为地址。
sed 10q foo q命令要求sed马上结束,这个命令可以打印foo的开头10行
最终行
符号$(就像在ed与ex里一样)指“最后一行”。下面的脚本指的就是快速打印文件最后一行。
sed -n '$p' "$1"
对sed而言,即便是处理多个人间,sed也将它们视为一个长的输入流,而$只应用到最后一个文件的最后一行(GNU的sed具有一个选项,可是地址分开地应用到每个文件)
范围
可指定行的范围,将地址以逗号隔开:
sed -n '10,42p' foo 打印10~42行
sed '/foo/,/bar/ s/baz/quux/g' 仅替换范围内的行,从含有foo的行开始,在第一个匹配到的bar
否定正则表达式
/used/! s/new/used/g 将没有used的每个行里所有的new改成used
POSIX标准明确指出:空白跟随!之后的行为是“未定义的”。
有多少文本会改动?
不想使用grep查找,你只要看看哪一行是什么就够了。sed进行文本替换,所以你要了解,究竟会替换确切的是多少字符。
从最左边开始,扩展至最长:正则表达式匹配可以匹配整个表达式的输入文本中最长的,最左边的子字符串。除此之外,匹配的空(null)字符串,则被认为是比完全不匹配的还长。(例如:ab*c匹配到ac,则b*成功匹配到ac之间的null)。
$echo Tolstoy is worldy | sed 's/T.*/Camus/'
Camus
这里只是想要匹配Tolstoy,但由于匹配会扩展到可能的最长长度的文本量,所有就到了worildy的y处。可以这样修改
$echo Tolstoy is worldly | sed 's/T[[:alpha:]]*y/Camus/'
Camus is worldly
举个匹配null的例子:
$echo abc | sed 's/b*/1/' 替换第一个匹配成功的
1abc
$echo abc | sed 's/b*/1/g' 替换所有匹配成功的
1a1c1
请留意,b*是如何匹配到abc的前面和结尾的null字符