sed 的使用
在Linux上工作,需要动态的处理文本,而不必使用完备的文本编辑器,在这样情况一上,拥有一个能够方便地格式化,插入,修改,删除,文本的简单命令行编辑器就很有用了。
linux上最常用的两个流编辑器sed和awk就是这样的工具。本文主要讨论sed的用法。
sed编辑器称为流编辑器,它每次只处理一行数据,将该数据与所提供的编辑器命令进行匹配,根据命令修改数据流中的数据,然后将新数据输出到stdout上,之后它将读取下一行数据,并重复上述的动作。处理完流数据中的全部数据之后,流编辑器停止。
sed命令不修改原文件的内容,只是将修改的结果显示出来而已,原文件不会改变。
sed的命令格式是:
sed options scripts file
options参数允许自定义sed的命令行为,它包含的选项如下:
选项 描述
-e scripts 将脚本中指定的命令添加到处理输入时执行的命令中
-f file 将文件中指定的命令添加到处理输入时执行的命令
-n 不需要为每个命令产生输出,但要等待打印命令,经常和-p 一起使用
scripts参数指定要应用于流数据的单个命令。如果需要多个命令,就必须使用 -e 命令, 或者使用-f 选项在单独的文件中指定。
一:在命令行中定义编辑器命令。
默认情况下,sed编辑器将指定的命令应用于STDIN输入流。这就允许将数据通过管道传送给sed编辑器进行处理。
如下面的一个例子。本文所以的例子都在root的家目录下进行的。
[root@linuxmoon ~]# echo "this is a test page" | sed 's/page/home/'
this is a test home
该例sed使用了 s 命令。s 用于将第二个字符串替换第一个字符串。本例home替换page
第二个字符串也可以有空格。如下red apple替换apple
[root@linuxmoon ~]# echo "this is an big apple" | sed 's/apple/red apple/'
this is an big red apple
也可以从文件中读取并处理,但原文件不会修改。如下:
[root@linuxmoon ~]# cat data1
this is an big apple
this is an big red apple
this is an small apple
this ia an small red apple
this is no an apple
[root@linuxmoon ~]# sed 's/apple/bird/' data1
this is an big bird
this is an big red bird
this is an small bird
this ia an small red bird
this is no an bird
查看原文件,仍然是原来的数据
[root@linuxmoon ~]# cat data1
this is an big apple
this is an big red apple
this is an small apple
this ia an small red apple
this is no an apple
[root@linuxmoon ~]#
本例中把文件data1中的所有的apple就替换成了bird
2.在命令行中输入多个命令
[root@linuxmoon ~]# cat data1
this is an big apple
this is an big red apple
this is an small apple
this ia an small red apple
this is no an apple
[root@linuxmoon ~]# sed -e 's/big/very big/;s/small/very small/' data1
this is an very big apple
this is an very big red apple
this is an very small apple
this ia an very small red apple
this is no an apple
[root@linuxmoon ~]#
两个命令将同时作用于文件中的每一行数据。命令必须用分号隔开,且在命令结尾和分号之间不能有空格。
也可以用命提示符,如下:
root@linuxmoon ~]# cat data1
this is an big apple
this is an big red apple
this is an small apple
this ia an small red apple
this is no an apple
[root@linuxmoon ~]# sed -e '
s/big/very big/
s/small/very small/' data1
this is an very big apple
this is an very big red apple
this is an very small apple
this ia an very small red apple
this is no an apple
[root@linuxmoon ~]#
3.从文件中读取编辑器命令
例如上面例子,我们把命令sed -e 's/big/very big/;s/small/very small/' data1 写入文件file1中。
[root@linuxmoon ~]# cat file1
s/big/very big/
s/small/very small/
[root@linuxmoon ~]# sed -f file1 data1
this is an very big apple
this is an very big red apple
this is an very small apple
this ia an very small red apple
this is no an apple
[root@linuxmoon ~]#
在这种情况下,不需要在每个命令后放一个分号。sed知道一行是一条命令。
sed编辑器的基础知识:
1.替换标记
对于替换命令替换文本字符,有一个小问题,首先先建立文件data2。以作演示。请看下面的例子。
[root@linuxmoon ~]# cat data2
this is the test of the test file
this is the second test of the test file
[root@linuxmoon ~]# sed 's/test/hello/' data2
this is the hello of the test file
this is the second hello of the test file
[root@linuxmoon ~]#
我们发现每一行的第一个test被替换掉了,但是每一行的第二个或者第三个。。。。都没有被替换。
即只替换每一行的第一个被匹配的test
如果想要全部替换,需要用替换标记(flags)。替换使用在替换命令之后:
s/pattern/replace/flags
可用的flags有4种
数字:表示替换第几个
g :全局替换
p :表示打印原始行的内容
w file :将替换的结果写入文件中
在第一种类型中,表示可以替换的第几个字符串,如下例:
[root@linuxmoon ~]# cat data2
this is the test of the test file
this is the second test of the test file
[root@linuxmoon ~]# sed 's/test/hello/2' data2
this is the test of the hello file
this is the second test of the hello file
[root@linuxmoon ~]#
在第二种类型中,g 表示全部替换:如下例:
[root@linuxmoon ~]# cat data2
this is the test of the test file
this is the second test of the test file
[root@linuxmoon ~]# sed 's/test/hello/g' data2
this is the hello of the hello file
this is the second hello of the hello file
[root@linuxmoon ~]#
在第三种类型中,p 表示只打印匹配的行,经常和-n一起使用。如下例:
[root@linuxmoon ~]# cat data2
this is the test of the test file
this is the second test of the test file
[root@linuxmoon ~]# sed -n 's/second/yes second/p' data2
this is the yes second test of the test file
[root@linuxmoon ~]#
本例中,只打印出了被匹配的行,未被匹配的行则不打印。
在第四种类型中,w 表示将sed修改后的内容保存到一个文件中。如下例
[root@linuxmoon ~]# cat data2
this is the test of the test file
this is the second test of the test file
[root@linuxmoon ~]# sed 's/test/hello/w hello.txt' data2
this is the hello of the test file
this is the second hello of the test file
[root@linuxmoon ~]# cat hello.txt
this is the hello of the test file
this is the second hello of the test file
[root@linuxmoon ~]#
本例将修改后的内容保存到了hello.txt文件中
2.替换字符
有时候在Linux中会遇到不容易替换的字符。最常用的一个例子就是斜杠。
例如,想要把/etc/passwd下的bash shell替换成cshell,必须这样做:
[root@linuxmoon ~]# sed 's/\/bin\/bash/\/bin\/cshell/g' /etc/passwd
这样会很乱,还容易搞混。为了解决这些问题,可以使用字符定界符。如上面的例子,可以用 “!”作定界符
[root@linuxmoon ~]# sed 's!/bin/bash!/bin/cshell!' /etc/passwd
3.行寻址
有时候仅仅想修改某一行或某些指定的行。那么就可以用行寻址了。行寻址分为两类:
1.行的数值范围
2.筛选行的文本模式
1.行的数值范围
[root@linuxmoon ~]# cat data3
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
[root@linuxmoon ~]# sed '2s/apple/dog/' data3
there is an apple on the desk
there is an dog on the desk
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
[root@linuxmoon ~]#
本例中,只替换第2行,下面是一个例子,替换第2行到第4行。使用的是行地址范围。
[root@linuxmoon ~]# cat data3
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
[root@linuxmoon ~]# sed '2,4s/apple/dog/' data3
there is an apple on the desk
there is an dog on the desk
there is an dog on the desk
there is an dog on the desk
there is an apple on the desk
[root@linuxmoon ~]#
如果要将命令应用于文本内从某一行到最后一行,我们可以使用特殊地址 $ 符号。下面例子是从第2 行到最后一行。
[root@linuxmoon ~]# cat data3
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
[root@linuxmoon ~]# sed '2,$s/apple/dog/' data3
there is an apple on the desk
there is an dog on the desk
there is an dog on the desk
there is an dog on the desk
there is an dog on the desk
[root@linuxmoon ~]#
2.筛选行的文本模式
限制某些命令应用于哪些行。
命令格式为:
/pattern/command
必须使用斜杠将标记指定的pattern,sed编辑器仅将该命令应用于包含文本模式的行。
如下面的例子,只替换含有second的行:
[root@linuxmoon ~]# cat data2
this is the test of the test file
this is the second test of the test file
[root@linuxmoon ~]# sed '/second/s/test/hello/' data2
this is the test of the test file
this is the second hello of the test file
[root@linuxmoon ~]#
组合命令
如果需要在单独一行上执行多个命令,请使用在括号将命令组合在一起。sed编辑器将处理地址行上列出的所有命令:
下面是一个示例:
[root@linuxmoon ~]# cat data3
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
[root@linuxmoon ~]# sed '2{
s/apple/banana/
s/desk/bed/
}' data3
there is an apple on the desk
there is an banana on the bed
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
[root@linuxmoon ~]#
本例中将第2行上的apple,desk分别替换为banana,bed ,两个命令都对该行作了处理。当然还可以使用行地址范围。如下例:
[root@linuxmoon ~]# cat data3
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
there is an apple on the desk
[root@linuxmoon ~]# sed '3,${
s/apple/banana/
s/desk/bed/
}' data3
there is an apple on the desk
there is an apple on the desk
there is an banana on the bed
there is an banana on the bed
there is an banana on the bed
[root@linuxmoon ~]#
本例中把第3行到最后一行的所有的apple,desk都替换成了banana,bed
二:删除行
删除命令为d ,即删除文本流中的特定行
用法如下
示例1:删除第3行
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '3d' data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
示例2:删除第2行到第4行
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '2,4d' data4
this is the a test line and is the 1
this is the a test line and is the 5
[root@linuxmoon ~]#
示例3:删除第2行到最后一行
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '2,$d' data4
this is the a test line and is the 1
[root@linuxmoon ~]#
示例4:删除含有特定字符串的行,本例中删除包含”the 2”的行。
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '/the 2/d' data4
this is the a test line and is the 1
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
注:sed编辑器不会处理原始文件。所删除的文本行仅从sed编辑器输出中删除,而原始文件仍然包含这些“已删除的行”。
三:插入和附加文本
同其它的编辑器一行,sed编辑器可以向文本中插入和附加文本。两个操作之间的差别很容易混淆。
插入命令( i ) 在指定行的前面插入新的一行。
附加命令( a ) 在指定行的后面附加新的一行。
示例1:使用 i 命令,在指定行的前面插入新的一行。
[root@linuxmoon ~]# echo "this is a line" |sed 'i test the command'
test the command
this is a line
[root@linuxmoon ~]#
示例2:使用 a 命令,在指定行的后面附加新的一行。
[root@linuxmoon ~]# echo "this is a line" |sed 'a test the command'
this is a line
test the command
[root@linuxmoon ~]#
示例3:使用数字指定在某一具体的行插入新的一行。本例在第2行插入新的一行。
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '2i this is the new line' data4
this is the a test line and is the 1
this is the new line
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
示例4:使用数字指定在某一具体的行附加新的一行。本例在第2行附加新的一行。
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '2a this is the new line' data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the new line
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
示例5:如果数据有多行,在尾部附加一行。可以使用 $ 符号,使用附加命令 a 。
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '$a this is the new line' data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
this is the new line
[root@linuxmoon ~]#
示例6:如果数据有多行,在最前面添加新的一行。可以使用相同的思路,在第一行插入新一行即可。使用插入命令 i .
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '1i this is the new line' data4
this is the new line
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
示例7:在指定的行前面插入或者附加多行。可以使用一个反斜杠。
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '1i\
the first one\
the second one ' data4
the first one
the second one
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
四:更改行
更改行命令允许更改数据流中的整行文本。指定该地址也可以使用文本模式。
示例1:更改某一具体的行。本例中更改第3行。
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '3c this is the changed line' data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the changed line
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
示例2:使用文本模式:
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '/the 3/c this is the changed line' data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the changed line
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
示例3:文本模式将更改与文本模式匹配的所有的行。本例中,有test的行。全部改变为hello
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '/test/c hello' data4
hello
hello
hello
hello
hello
[root@linuxmoon ~]#
示例4:使用行地址范围,但结果可能不是预期的效果。
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '2,3c this is the changed line' data4
this is the a test line and is the 1
this is the changed line
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
注:本例中,sed编辑器没有用文本更改两行,而是使用单一行文本替换了两行文本。
五:变换命令
变换命令(y)是唯一对单个字符进行操作的sed编辑器命令。变换命令使用的格式为:
[address]y/inchars/outchars/
变换命令将inchars和outchars的值进行一对一映射。将inchars中的第一个字符转换为outchars中的第一个字符。将inchars中的第二个字符转换为outchars中的第二个字符。以此类推。
示例1:一对一映射。将123分别替换成789
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed 'y/123/789/' data4
this is the a test line and is the 7
this is the a test line and is the 8
this is the a test line and is the 9
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
注:变换命令是全局命令,也就是说,它自动对在文本行中发现的任意字符进行变换,而不管其是第几次出现。下面作一个示例:
示例2:
[root@linuxmoon ~]# echo "the 2 is the test number 2 " |sed 'y/2/8/'
the 8 is the test number 8
[root@linuxmoon ~]#
六:打印命令
sed编辑器有3个命令也可以用于打印来自数据流的信息:
打印文本行的小写p命令
打印行号的等号(=)命令
列出行的l (小写L)命令
1.打印行
与替换命令中的p标记类似,p命令打印sed编辑器输出中的一行,单独使用p命令没有什么效果:如下例。
示例1:
[root@linuxmoon ~]# echo "test line" |sed 'p'
test line
test line
[root@linuxmoon ~]#
它所做的只是打印已知的文本。打印命令最常用的是打印包含匹配模式的行。如下例。
示例2:
[root@linuxmoon ~]# cat data5
this is the test line
this is not the test line
this is the new line
[root@linuxmoon ~]# sed -n '/not/p' data5 #使用-n 选项,只打印包含匹配模式的行
this is not the test line
[root@linuxmoon ~]# sed '/not/p' data5 #没有使用-n选项,把所有的行都打印出来了,包括未匹配的行
this is the test line
this is not the test line
this is not the test line
this is the new line
[root@linuxmoon ~]#
示例3:打印行号的另一个用途是改变某行前查看该行。如利用替换或更改命令,可以创建脚本在一行更改之前显示该行。如下例:
[root@linuxmoon ~]# cat data5
this is the test line
this is not the test line
this is the new line
[root@linuxmoon ~]# sed -n '/not/{
p
s/not/hello/p
}' data5
this is not the test line
this is hello the test line
[root@linuxmoon ~]#
本例先查看含有not的行。然后把此行的not 更换为hello,并且打印出来。
2.打印行号
等号命令打印数据流内的当前行的行号。
示例1:打印行号
[root@linuxmoon ~]# sed '=' data5
1
this is the test line
2
this is not the test line
3
this is the new line
[root@linuxmoon ~]#
示例2:打印匹配的行以及行号
[root@linuxmoon ~]# cat data5
this is the test line
this is not the test line
this is the new line
[root@linuxmoon ~]# sed -n '/not/{
=
p
}' data5
2
this is not the test line
[root@linuxmoon ~]#
七:将文件用于sed
替换命令包含允许你处理文件的标记。也有正规的sed编辑器命令允许你处理文件而不必替换文本。
1.写文件
w 命令用于将文本行写入文件。使用格式为:
[address]w filename
filename可以指定为相对路径或绝对路径,但在任意一种情况下,运行sed编辑器的用户必须对该文件有写权限,地址可以使用sed中任意类型的寻址方法。
示例1:将数据流的前两行写入文件test中。
[root@linuxmoon ~]# cat data5
this is the test line
this is not the test line
this is the new line
[root@linuxmoon ~]# sed '1,2w test' data5
this is the test line
this is not the test line
this is the new line
[root@linuxmoon ~]# cat test
this is the test line
this is not the test line
[root@linuxmoon ~]#
示例2:如上例,如果不想在stdout上显示出来,也可以使用 –n 选项
[root@linuxmoon ~]# cat data5
this is the test line
this is not the test line
this is the new line
[root@linuxmoon ~]# sed -n '2,3w test' data5
[root@linuxmoon ~]# cat test
this is not the test line
this is the new line
[root@linuxmoon ~]#
示例3:文本匹配模式。本例仅把匹配的行写入test文件中。
[root@linuxmoon ~]# cat data5
this is the test line
this is not the test line
this is the new line
[root@linuxmoon ~]# sed -n '/not/w test' data5
[root@linuxmoon ~]# cat test
this is not the test line
[root@linuxmoon ~]#
2.从文件中读取数据。
前面介绍了向数据流中插入或附加文本的方法。读命令(r)允许你插入包含在独立文件中的数据。
读命令的格式为 [address]r filename
filename参数可以为绝对路径也可以是相对路径。对于读命令,不能使用地址范围。只能指定单一的行号或文本模式。sed编辑器在该地址之后插入文件中的文本。
示例1:使用行号。本例中把文件data5中的内容插入到文件data4的第3行之后。
[root@linuxmoon ~]# cat data5
this is the test line
this is not the test line
this is the new line
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '3r data5' data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the test line
this is not the test line
this is the new line
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
示例2:使用文本模式
[root@linuxmoon ~]# cat data5
this is the test line
this is not the test line
this is the new line
[root@linuxmoon ~]# cat data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]# sed '/the 2/r data5' data4
this is the a test line and is the 1
this is the a test line and is the 2
this is the test line
this is not the test line
this is the new line
this is the a test line and is the 3
this is the a test line and is the 4
this is the a test line and is the 5
[root@linuxmoon ~]#
小结:尽管shell可以完成很多的工作,但仅仅会shell脚本还是很难处理数据。linux提供了两个强大的的实用工具来辅助处理文本数据。sed编辑器是能够在读取
数据时动态处理数据。
gawk程序是来自GNU组织的一个实用程序,它能够模拟和扩展Unix shell的awk程序的功能。
sed和awk程序的至关重要的一点是可以使用正则表达式,正则表达式是创建自定义筛选器抽取和处理文本文件中的数据的关键。
如果还要更好的处理linux日常的任务,最好还要学一门其它的脚本语言,比如有时候可以自己开发一些小工具,个人推荐perl,python
查看文件内容的指定行 特殊方法
- 如果你只想看文件的前5行,可以使用head命令,如:
head -5 /etc/passwd - 如果你想查看文件的后10行,可以使用tail命令,如:
tail -10 /etc/passwd
tail -f /var/log/messages
参数-f使tail不停地去读最新的内容,这样有实时监视的效果,当你在ppp拨号的过程中用它岂不是很方便! - 查看文件中间一段,你可以使用sed命令,如:
sed -n '5,10p' /etc/passwd
这样你就可以只查看文件的第5行到第10行