我们晓得,Vim采用的是交互式文本编辑模式,你可以用鼠标命令来交互性地插入、删除或替换数据中的文本。但本节要讲的sed命令不同,它采用的是流编辑模式,最显著的特征是,在sed处理数据之前,须要预先提供一组规则,sed会根据此规则来编辑数据。
sed会按照脚本命令来处理文本文件中的数据,这种命令要么从命令行中输入,要么储存在一个文本文件中,此命令执行数据的次序如下:每次仅读取一行内容;按照提供的规则命令匹配并更改数据。注意,sed默认不会直接更改源文件数据,而是会将数据复制到缓冲区中,更改也仅限于缓冲区中的数据;将执行结果输出。当一行数据匹配完成后,它会继续读取下一行数据,并重复这个过程,直至将文件中所有数据处理完毕。
sed命令的基本格式如下:
[root@localhost~]#sed[选项][脚本命令]文件名
该命令常用的选项及涵义,如表1所示。
表1sed命令常用选项及涵义选项涵义
-e脚本命令
该选项会将其后跟的脚本命令添加到已有的命令中。
-f脚本命令文件
该选项会将其后文件中的脚本命令添加到已有的命令中。
-n
默认情况下,sed会在所有的脚本指定执行完毕后,会手动输出处理后的内容,而该选项会屏蔽启动输出,需使用print命令来完成输出。
-i
此选项会直接更改源文件,要慎用。
成功使用sed命令的关键在于把握各色各样的脚本命令及格式,它能帮你订制编辑文件的规则。
sed脚本命令seds替换脚本命令此命令的基本格式为:
[address]s/pattern/replacement/flags
其中,address表示指定要操作的具体行,pattern指的是须要替换的内容,replacement指的是要替换的新内容。
关于指定具体操作行(address)的用法,这儿先不做解释,文章后续会对其做详尽介绍。
此命令中常用的flags标记如表2所示。
表2seds命令flags标记及功能flags标记功能
1~512之间的数字,表示指定要替换的字符串出现第几次时才进行替换,比如,一行中有3个A,但用户只想替换第二个A,这是就用到这个标记;
对数据中所有匹配到的内容进行替换,假如没有g,则只会在第一次匹配成功时做替换操作。诸如,一行数据中有3个A,则只会替换第一个A;
会复印与替换命令手指定的模式匹配的行。此标记一般与-n选项一起使用。
wfile
将缓冲区中的内容讲到指定的file文件中;
用正则表达式匹配的内容进行替换;
n
匹配第n个子串,该子串之前在pattern中用()指定。
通配符(通配符替换部份包含:&、等)。
例如,可以指定sed用新文本替换第几处模式匹配的地方:
[root@localhost~]#sed's/test/trial/2'data4.txt
Thisisatestofthetrialscript.
Thisisthesecondtestofthetrialscript.
可以看见,使用数字2作为标记的结果就是,sed编辑器只替换每行中第2次出现的匹配模式。
假如要用新文件替换所有匹配的字符串,可以使用g标记:
[root@localhost~]#sed's/test/trial/g'data4.txt
Thisisatrialofthetrialscript.
Thisisthesecondtrialofthetrialscript.
我们晓得,-n选项会严禁sed输出,但p标记会输出更改过的行,将两者匹配使用的疗效就是只输出被替换命令更改过的行,比如:
[root@localhost~]#catdata5.txt
Thisisatestline.
Thisisadifferentline.
[root@localhost~]#sed-n's/test/trial/p'data5.txt
Thisisatrialline.
w标记会将匹配后的结果保存到指定文件中,例如:
[root@localhost~]#sed's/test/trial/wtest.txt'data5.txt
Thisisatrialline.
Thisisadifferentline.
[root@localhost~]#cattest.txt
Thisisatrialline.
在使用s脚本命令时,替换类似文件路径的字符串会比较麻烦,须要将路径中的正斜线进行通配符,比如:
[root@localhost~]#sed's//bin/bash//bin/csh/'/etc/passwd
sedd替换脚本命令此命令的基本格式为:
[address]d
假如须要删掉文本中的特定行,可以用d脚本命令,它会删掉指定行中的所有内容。但使用该命令时要非常当心,假如你忘掉指定具体行的话,文件中的所有内容还会被删掉linux相关命令,举个反例:
[root@localhost~]#catdata1.txt
Thequickbrownfoxjumpsoverthelazydog
Thequickbrownfoxjumpsoverthelazydog
Thequickbrownfoxjumpsoverthelazydog
Thequickbrownfoxjumpsoverthelazydog
[root@localhost~]#sed'd'data1.txt
#哪些也不输出,证明成了空文件
当和指定地址一起使用时,删掉命令似乎能发挥出大的功用。可以从数据流中删掉特定的文本行。
address的具体写法后续会做详尽介绍,这儿只给你们举几个简单的事例:在此指出,在默认情况下sed并不会更改原始文件,这儿被删掉的行只是从sed的输出中消失了,原始文件没做任何改变。
seda和i脚本命令a命令表示在指定行的前面附加一行,i命令表示在指定行的后面插入一行,这儿之所以要同时介绍这2个脚本命令,由于它们的基本格式完全相同,如下所示:
[address]a(或i)新文本内容
下边分别就这2个命令,给读者举几个反例。例如说,将一个新行插入到数据流第三行前,执行命令如下:
[root@localhost~]#sed'3i
>Thisisaninsertedline.'data6.txt
Thisislinenumber1.
Thisislinenumber2.
Thisisaninsertedline.
Thisislinenumber3.
Thisislinenumber4.
再譬如说,将一个新行附加到数据流中第三行后,执行命令如下:
[root@localhost~]#sed'3a
>Thisisanappendedline.'data6.txt
Thisislinenumber1.
Thisislinenumber2.
Thisislinenumber3.
Thisisanappendedline.
Thisislinenumber4.
假如你想将一个多行数据添加到数据流中,只需对要插入或附加的文本中的每一行末尾(除最后一行)添加反斜线即可,比如:
[root@localhost~]#sed'1i
>Thisisonelineofnewtext.
>Thisisanotherlineofnewtext.'data6.txt
Thisisonelineofnewtext.
Thisisanotherlineofnewtext.
Thisislinenumber1.
Thisislinenumber2.
Thisislinenumber3.
Thisislinenumber4.
可以看见,指定的两行就会被添加到数据流中。
sedc替换脚本命令c命令表示将指定行中的所有内容,替换成该选项前面的字符串。该命令的基本格式为:
[address]c用于替换的新文本
举个反例:
[root@localhost~]#sed'3c
>Thisisachangedlineoftext.'data6.txt
Thisislinenumber1.
Thisislinenumber2.
Thisisachangedlineoftext.
Thisislinenumber4.
在这个事例中,sed编辑器会更改第三行中的文本,当然,下边的写法也可以实现此目的:
[root@localhost~]#sed'/number3/c
>Thisisachangedlineoftext.'data6.txt
Thisislinenumber1.
Thisislinenumber2.
Thisisachangedlineoftext.
Thisislinenumber4.
sedy转换脚本命令y转换命令是惟一可以处理单个字符的sed脚本命令,其基本格式如下:
[address]y/inchars/outchars/
转换命令会对inchars和outchars值进行一对一的映射,即inchars中的第一个字符会被转换为outchars中的第一个字符,第二个字符会被转换成outchars中的第二个字符...这个映射过程会仍然持续到处理完指定字符。假如inchars和outchars的厚度不同,则sed会形成一条错误消息。
举个简单事例:
[root@localhost~]#sed'y/123/789/'data8.txt
Thisislinenumber7.
Thisislinenumber8.
Thisislinenumber9.
Thisislinenumber4.
Thisislinenumber7again.
Thisisyetanotherline.
Thisisthelastlineinthefile.
可以看见,inchars模式手指定字符的每位实例就会被替换成outchars模式中相同位置的哪个字符。
转换命令是一个全局命令,也就是说,它会文本行中找到的所有指定字符手动进行转换,而不会考虑它们出现的位置,再打个比方:
[root@localhost~]#echo"This1isatestof1try."|sed'y/123/456/'
This4isatestof4try.
sed转换了在文本行中匹配到的字符1的两个实例红旗linux操作系统,我们没法限定只转换在特定地方出现的字符。
sedp复印脚本命令p命令表示搜索符号条件的行,并输出该行的内容,此命令的基本格式为:
[address]p
p命令常见的用法是复印包含匹配文本模式的行,比如:
[root@localhost~]#catdata6.txt
Thisislinenumber1.
Thisislinenumber2.
Thisislinenumber3.
Thisislinenumber4.
[root@localhost~]#sed-n'/number3/p'data6.txt
Thisislinenumber3.
可以见到,用-n选项和p命令配合使用,我们可以严禁输出其他行,只复印包含匹配文本模式的行。
假如须要在更改之前查看行,也可以使用复印命令,例如与替换或更改命令一起使用。可以创建一个脚本在更改行之前显示该行,如下所示:
[root@localhost~]#sed-n'/3/{
>p
>s/line/test/p
>}'data6.txt
Thisislinenumber3.
Thisistestnumber3.
sed命令会查找包含数字3的行,之后执行两条命令。首先,脚本用p命令来复印出原始行;之后它用s命令替换文本,并用p标记复印出替换结果。输出同时显示了原先的行文本和新的行文本。sedw脚本命令w命令拿来将文本手指定行的内容写入文件中,此命令的基本格式如下:
[address]wfilename
这儿的filename表示文件名,可以使用相对路径或绝对路径linux相关命令,但不管是哪种,运行sed命令的用户都必须有文件的写权限。
下边的事例是将数据流中的前两行复印到一个文本文件中:
[root@localhost~]#sed'1,2wtest.txt'data6.txt
Thisislinenumber1.
Thisislinenumber2.
Thisislinenumber3.
Thisislinenumber4.
[root@localhost~]#cattest.txt
Thisislinenumber1.
Thisislinenumber2.
其实,假若不想让行直接输出,可以用-n选项,再举个反例:
[root@localhost~]#catdata11.txt
Blum,RBrowncoat
McGuiness,AAlliance
Bresnahan,CBrowncoat
Harken,CAlliance
[root@localhost~]#sed-n'/Browncoat/wBrowncoats.txt'data11.txt
catBrowncoats.txt
Blum,RBrowncoat
Bresnahan,CBrowncoat
可以看见,通过使用w脚本命令,sed可以实现将包含文本模式的数据行写入目标文件。sedr脚本命令r命令用于将一个独立文件的数据插入到当前数据流的指定位置,该命令的基本格式为:
[address]rfilename
sed命令会将filename文件中的内容插入到address指定行的旁边,例如说:
[root@localhost~]#catdata12.txt
Thisisanaddedline.
Thisisthesecondaddedline.
[root@localhost~]#sed'3rdata12.txt'data6.txt
Thisislinenumber1.
Thisislinenumber2.
Thisislinenumber3.
Thisisanaddedline.
Thisisthesecondaddedline.
Thisislinenumber4.
假如你想将指定文件中的数据插入到数据流的末尾,可以使用$地址符,比如:
[root@localhost~]#sed'$rdata12.txt'data6.txt
Thisislinenumber1.
Thisislinenumber2.
Thisislinenumber3.
Thisislinenumber4.
Thisisanaddedline.
Thisisthesecondaddedline.
sedq退出脚本命令q命令的作用是使sed命令在第一次匹配任务结束后,退出sed程序,不再进行对后续数据的处理。
例如:
[root@localhost~]#sed'2q'test.txt
Thisislinenumber1.
Thisislinenumber2.
可以看见,sed命令在复印输出第2行以后,就停止了,是q命令导致的,再例如:
[root@localhost~]#sed'/number1/{s/number1/number0/;q;}'test.txt
Thisislinenumber0.
使用q命令以后,sed命令会在匹配到number1时,将其替换成number0,之后直接退出。
sed脚本命令的轮询方法上面在介绍各个脚本命令时,我们仍然忽视了对address部份的介绍。对各个脚本命令来说,address拿来表明该脚本命令作用到文本中的具体行。
默认情况下,sed命令会作用于文本数据的所有行。若果只想将命令作用于特定行或个别行,则必须写明address部份,表示的方式有以下2种:
以数字方式指定行区间;用文本模式指定具体行区间。
以上两种方式都可以使用如下这2种格式,分别是:
[address]脚本命令
或则
address{
多个脚本命令
以上两种方式在上面事例中都有具体实例,因而这儿不再做过多赘言。
以数字方式指定行区间当使用数字形式的行轮询时,可以用行在文本流中的行位置来引用。sed会将文本流中的第一行编号为1,之后继续按次序为接出来的行分配行号。
在脚本命令中,指定的地址可以是单个行号,或是用起始行号、逗号以及结尾行号指定的一定区间范围内的行。这儿举一个sed命令作用到指定行号的事例:
[root@localhost~]#sed'2s/dog/cat/'data1.txt
Thequickbrownfoxjumpsoverthelazydog
Thequickbrownfoxjumpsoverthelazycat
Thequickbrownfoxjumpsoverthelazydog
Thequickbrownfoxjumpsoverthelazydog
可以看见,sed只更改地址指定的第二行的文本。下边的事例中使用了行地址区间:
[root@localhost~]#sed'2,3s/dog/cat/'data1.txt
Thequickbrownfoxjumpsoverthelazydog
Thequickbrownfoxjumpsoverthelazycat
Thequickbrownfoxjumpsoverthelazycat
Thequickbrownfoxjumpsoverthelazydog
在此基础上,假如想将命令作用到文本中从某行开始的所有行,可以用特殊地址——美元符($):
[root@localhost~]#sed'2,$s/dog/cat/'data1.txt
Thequickbrownfoxjumpsoverthelazydog
Thequickbrownfoxjumpsoverthelazycat
Thequickbrownfoxjumpsoverthelazycat
Thequickbrownfoxjumpsoverthelazycat
用文本模式指定行区间sed容许指定文本模式来过滤出命令要作用的行,格式如下:
/pattern/command
注意,必须用正斜线即将指定的pattern封上去,sed会将该命令作用到包含指定文本模式的行上。
举个事例,假如你想只更改用户demo的默认shell,可以使用sed命令,执行命令如下:
[root@localhost~]#grepdemo/etc/passwd
demo:x:502:502::/home/Samantha:/bin/bash
[root@localhost~]#sed'/demo/s/bash/csh/'/etc/passwd
root:x:0:0:root:/root:/bin/bash
...
demo:x:502:502::/home/demo:/bin/csh
...
即使使用固定文本模式能帮你过滤出特定的值,就跟前面这个用户名的事例一样,但其作用难免有限,因而,sed准许在文本模式使用正则表达式指明作用的具体行。正则表达式容许创建中级文本模式匹配表达式来匹配各类数据。这种表达式结合了一系列键值、特殊字符以及固定文本字符来世成才能匹配几乎任何方式文本的简短模式。
关于正则表达式linux系统介绍,本节不做过多介绍,有兴趣的读者可阅读《正则表达式入门教程》一文,这儿仅给读者提供一个简单示例:
[root@localhost~]#cattest.txt
FirstWed
h1Helloh1
h2Helloh2
h3Helloh3
#使用正则表示式给所有第一个的h1、h2、h3添加,给第二个h1、h2、h3添加
[root@localhost~]#catsed.sh
/h[0-9]/{
s///1
s///2
[root@localhost~]#sed-fsed.shtest.txt
Hello
Hello
Hello
收到篇幅的限制,本节仅介绍了sed命令每次只读取一行内容并处理,有关sed命令怎么一次处理多行文本内容,放在下节继续讲解,读者可点击《Linuxsed命令中级用法》继续学习。