SED
sed编辑器基础
sed是用来解析和转换文本的工具,是简洁的程序设计语言。来自贝尔实验室。
sed简介
sed是非交互式的面向数据流的编辑器,提供了交互式文本编辑器的自然扩展功能。有助于编写简单的shell脚本,如:替换文本、删除某行、差入新文本等。
sed特点:
-
自动化地编辑一个或多个文件
-
简化在多个文件中执行相同操作的任务
-
编写转换程序
模式空间
模式空间类似于一个工作区或临时缓冲区。sed操作的不是郑振的文本,而是一个类似快照的东西。sed一次处理一行数据,这就避免了将一个很大的文件读入内存,而产生内存益处或者处理速度过慢的情况。
基本的sed编辑命令
sed从标准数入获取数入并发送输出到标准输出。sed命令的语法有两种:在命令行指定或将sed放入一个文件并将其文件名作为参数:
sed [OPTIONS]... 'COMMAND' [FILE]...
sed [OPTIONS] -f SCRIPTFILE [FILE]...
sed有一些常用的选项:
-
-e:告诉sed将下一个参数解释为sed指令,只有在命令行上给出多个sed指令才需要使用-e选项
-
-f:指定由sed指令组成的脚本名称。如果sed脚本的第一行位"#n",则sed的行为与指定-n选项相同
-
-i:直接修改读取的内容,而不是输出到终端
-
-n:取消默认输出;一般情况下,sed处理后整个文件内容都会输出到终端,但是使用-n后,只由经过sed处理的行才会被显示出来
sed指令由地址和编辑命令组成。如果指令的地址被匹配到,那么编辑命令就被应用到匹配的行。sed的编辑命令由24个,常用的有:追加(a)、更改(c)、删除(d)、插入(i)、替换(s)、打印(l)、打印行号(=)、转换(y)。
追加、更改、插入编辑命令
追加命令将文本放置在当前行之后;更改命令用所指定的文本取代模式空间的内容;插入命令将所提供的文本在模式空间的当前行之前。这些命令中的每个都要求后面跟一个反斜杠用于转义第一个行尾,text必须从下一行开始。要输入多行文本,每个连续的行都必须反斜杠结束,最后一行除外。如果文本中包含了一个字面含义的反斜杠,需要转义。
如:
文本内容:
[root@localhost sed]# cat test.txt I like YOU but just LIKE you you should be brave and harry
追加一行内容:
[root@localhost sed]# sed '$a<end of the file>' test.txt I like YOU but just LIKE you you should be brave and harry <end of the file>
$是寻址符号,用于匹配文件的最后一行。提供的文本在前行之后输出,所以输出到了最后一行
更改数据
插入数据:如,给test.txt文件插入一行数据(第一行插入"#!/bin/bash")
[root@localhost sed]# sed 1i\#\!/bin/bash test.txt #!/bin/bash I like YOU but just LIKE you you should be brave and harry
删除编辑命令
删除编辑命令采用一个地址,如果行匹配到该地址,就删除内容。
如:
删除文件中的空行
[root@localhost sed]# sed '/^$/d' test.txt I like YOU but just LIKE you you should be brave and harry
也可以删除指定的行
[root@localhost sed]# sed '1d' test.txt you should be brave and harry
删除了第一行
甚至删除一个范围内的行
[root@localhost sed]# sed '2,$d' test.txt I like YOU but just LIKE you
删除了第二行之后所有的行
替换编辑命令
替换编辑命令算是sed一个特别重要的命令了,具体语法:
[address]s/pattern/replacement/flags
flages是替换命令的修饰标志,有如下几个:
-
n——1~512之间的数字,表示对文本模式pattern中指定模式第n次出现的情况进行替换
-
g——对模式空间所有匹配的进行替换,如果没有g,一般替换第一次出现的匹配
-
p——打印模式空间的内容
-
w file——将模式空间的内容写入到file中
替换命令用于地址匹配的行,如果没有指定地址,就应用于所有的行。
replacement是一个字符串,用来替换与模式匹配的内容。replacement有由几个字符有特殊含义:
-
&——由正则表达式匹配的字符串进行替换
-
\n——匹配第n个字符串,这个字符串时在pattern(模式)中指定的
-
\——用于转义符号&或\
如:
[root@localhost sed]# cat sedsub s/I/He/1 [root@localhost sed]# sed -f sedsub test.txt He like YOU but just LIKE you you should be brave and harry
打印行号编辑命令
跟在地址后面的等号用来打印被匹配到的行的行号。
如:
[root@localhost sed]# sed = test.txt 1 I like YOU but just LIKE you 2 3 you should be brave and harry
sed命令实例
操作文件test.txt
[root@localhost sed]# cat test.txt I like YOU but just LIKE you you should be brave and harry
向文件中添加或插入行
实例1:在文件的指定行之后添加一行内容
如:在test.txt文件第二行添加一行数据
[root@localhost sed]# sed '2a this is a row for test' test.txt I like YOU but just LIKE you this is a row for test you should be brave and harry
实例2:在匹配模式的行之后添加一行内容
[root@localhost sed]# sed '/harry/a this is a test for exaple2' test.txt I like YOU but just LIKE you you should be brave and harry this is a test for exaple2
实例3:在文件的最后一行添加多行内容
[root@localhost sed]# sed '$a\ > this is test line 1 \ > this is test line 2' test.txt I like YOU but just LIKE you you should be brave and harry this is test line 1 this is test line 2
实例4:在文件中的指定行前插入数据
在第三行前添加一行数据:
[root@localhost sed]# sed '3i this is a test' test.txt I like YOU but just LIKE you this is a test you should be brave and harry
实例5:在匹配模式的行至前添加一行内容
[root@localhost sed]# sed '/harry/i this is a test' test.txt I like YOU but just LIKE you this is a test you should be brave and harry [root@localhost sed]# sed '/^$/i this is a test' test.txt I like YOU but just LIKE you this is a test you should be brave and harry
实例6:在文件最后一行至前插入年内容
[root@localhost sed]# sed '$i this is a test' test.txt I like YOU but just LIKE you this is a test you should be brave and harry
更改文件中指定的行
实例1:修改文件第一行
[root@localhost sed]# sed '1c this is a test' test.txt this is a test you should be brave and harry
实例2:修改匹配模式的行
[root@localhost sed]# sed '/^$/c this is a test' test.txt I like YOU but just LIKE you this is a test you should be brave and harry
实例3:更改最后一行
[root@localhost sed]# sed '$c this is a test' test.txt I like YOU but just LIKE you this is a test
删除文件中的行
有文件test.txt,同删除测试。
[root@localhost sed]# cat test.txt I like YOU but just LIKE you you should be brave and harry life was amazing 1234567890 run from cmd exopse copy add volume maintainer
实例1:删除文件中指定的行,删除test.txt中的第2行
[root@localhost sed]# sed '2d' test.txt I like YOU but just LIKE you you should be brave and harry life was amazing 1234567890 run from cmd exopse copy add volume maintainer
实例2:从指定的行开始删除,并每个固定的行数删除一行。从第一行开始删除,每个二行删除一行
[root@localhost sed]# sed '1~2d' test.txt life was amazing run from cmd exopse copy add volume maintainer
实例3:删除指定范围的行,删除2-3行数据
[root@localhost sed]# sed '2,3d' test.txt I like YOU but just LIKE you life was amazing 1234567890 run from cmd exopse copy add volume maintainer
实例4:删除指定范围内的行,删除除第二三行外所有的行
[root@localhost sed]# sed '2,3!d' test.txt you should be brave and harry
实例5:删除文件中最后一行
[root@localhost sed]# sed '$d' test.txt I like YOU but just LIKE you you should be brave and harry life was amazing 1234567890
实例6:删除文件中匹配模式指定的行。删除含有YOU的行
[root@localhost sed]# sed '/YOU/d' test.txt you should be brave and harry life was amazing 1234567890 run from cmd exopse copy add volume maintainer
实例7:从匹配模式的行删除到指定的行,匹配到YOU,开始删除到第2行
[root@localhost sed]# sed '/YOU/, 2d' test.txt you should be brave and harry life was amazing 1234567890 run from cmd exopse copy add volume maintainer
实例8:删除文件中匹配指定模式的行以及之后n行数据,删除匹配到YOU,和之后3行的数据
[root@localhost sed]# sed '/YOU/, +3d' test.txt 1234567890 run from cmd exopse copy add volume maintainer
实例9:删除文件中的空白行
[root@localhost sed]# sed '/^$/d' test.txt I like YOU but just LIKE you you should be brave and harry life was amazing 1234567890 run from cmd exopse copy add volume maintainer
实例10:删除文件中不匹配指定模式的行,删除匹配不到YOU的所有行
[root@localhost sed]# sed '/YOU/!d' test.txt I like YOU but just LIKE you
实例11:删除文件的指定范围内的匹配到匹配模式的行,删除3-5行中匹配到you的行
[root@localhost sed]# sed '3,5{/you/d}' test.txt I like YOU but just LIKE you life was amazing 1234567890 run from cmd exopse copy add volume maintainer
替换文件中的内容
使用文件test.txt作为测试文件。
[root@localhost sed]# cat test2.txt I like YOU but just LIKE you 1 you should be brave and harry you you 3 life was amazing 4 1234567890 5 run from cmd exopse copy add volume maintainer 6
实例1:替换一行中第一个匹配到的字符串,将每一行匹配到的第一个you替换成he
[root@localhost sed]# sed 's/you/he/' test2.txt I like YOU but just LIKE he 1 he should be brave and harry you you 3 life was amazing 4 1234567890 5 run from cmd exopse copy add volume maintainer 6
第三行后面还有两个you,但是不会被匹配到
实例2:替换文件中的匹配指定模式的所有字符串,将每一行匹配到的所有you替换成he
[root@localhost sed]# sed 's/you/he/g' test2.txt I like YOU but just LIKE he 1 he should be brave and harry he he 3 life was amazing 4 1234567890 5 run from cmd exopse copy add volume maintainer 6
实例3:替换文件中每行第n个匹配指定模式的字符串,将匹配到的第二个you替换成he
[root@localhost sed]# sed 's/you/he/2' test2.txt I like YOU but just LIKE you 1 you should be brave and harry he you 3 life was amazing 4 1234567890 5 run from cmd exopse copy add volume maintainer 6
实例4:将发生字符串替换的行写入指定的文件,并打印只替换的行
[root@localhost sed]# sed -n 's/you/he/gpw output.txt' test2.txt I like YOU but just LIKE he 1 he should be brave and harry he he 3 [root@localhost sed]# cat output.txt I like YOU but just LIKE he 1 he should be brave and harry he he 3
注意:g是全局,p是打印,w是写入文件,-n是静默模式(不打印到标准输出)
实例5:只替换文件中匹配指定模式的行中的字符串
[root@localhost sed]# sed '3{s/you/he/g}' test2.txt I like YOU but just LIKE you 1 he should be brave and harry he he 3 life was amazing 4 1234567890 5 run from cmd exopse copy add volume maintainer 6
实例6:删除每行最后的n个字符。删除每行最后三个字符
[root@localhost sed]# sed 's/...$//g' test2.txt I like YOU but just LIKE yo you should be brave and harry you yo life was amazin 123456789 run from cmd exopse copy add volume maintaine
实例7:删除文件中的注释
[root@localhost sed]# sed 's/^#.*//' test2.txt I like YOU but just LIKE you 1 you should be brave and harry you you 3 life was amazing 4 1234567890 5 run from cmd exopse copy add volume maintainer 6
实例8:删除文件中以"#"号开头的注释及空行
[root@localhost sed]# sed '/^#/d;/^$/d' test2.txt I like YOU but just LIKE you 1 you should be brave and harry you you 3 life was amazing 4 1234567890 5 run from cmd exopse copy add volume maintainer 6
sed与shell
在sed中使用shell变量
shell中环境变量以"$"开头,而在sed中,符号"$"用于只是输出文件中的最后一行或行尾(正则表达)。sed不能直接访问SHELL中的变量,所以必须使用双引号来扩展shell变量。
如果想要shell正确解释sed命令中的shell变量,就要将sed指令放在双引号内。如:
[root@localhost sed]# cat input.file the name of terminal which you are using is _terminal-type_. [root@localhost sed]# sed "s/_terminal-type_./$TERM/g" input.file the name of terminal which you are using is xterm-256color
如果用的是单引号,则$不会被认为是引用:
[root@localhost sed]# sed 's/_terminal-type_./$TERM/g' input.file the name of terminal which you are using is $TERM
test.txt用于进行测试,文件内容如下:
[root@localhost 14_4]# cat test.txt I like YOU but JUST like you 狗肉汤就是用狗肉炖成的汤 rr wrr source_hash desternation_hash #lc wlc sed nq lblc lblcr
实例1:
移除文件中空白行的shell脚本:removeblanklines.sh
脚本内容:
[root@localhost 14_4]# cat RemoveBlankLines.sh #!/bin/bash #移除文件中的空白行 #检查传递给脚本的参数,如果没有指定参数,则打印脚本使用方法 if [ -z "$1" ] then echo "Usage: `basename $0` traget-file." #退出脚本,退出状态码为1 exit 1 fi sed -e "/^$/d" "$1" #其中,-e表示后跟一个编辑命令 # ^$,表示模式匹配空白行 # d指定删除 # 这里只是在模式空间中修改,如果要修改真正文本,加-i选项 exit 0
执行结果:
[root@localhost 14_4]# bash RemoveBlankLines.sh test.txt I like YOU but JUST like you 狗肉汤就是用狗肉炖成的汤 rr wrr source_hash desternation_hash #lc wlc sed nq lblc lblcr
实例2:替换文件中的字符串的脚本:substituteStr.sh
脚本内容:
[root@localhost 14_4]# cat substituteStr.sh #!/bin/bash #替换文件中字符串的脚本 #检查传递给脚本的参数,如果没有指定参数,则打印脚本使用方法 if [ $# != 3 ] then echo "Usage: `basename $0` old_sting new_string traget-file." #退出脚本,退出状态码为1 exit 1 fi if [ -f "$3" ] then sed -e "s/$1/$2/g" "$3" else echo "file does not exits." fi # 这里只是在模式空间中修改,如果要修改真正文本,加-i选项 exit 0
执行结果:
[root@localhost 14_4]# bash substituteStr.sh Usage: substituteStr.sh old_sting new_string traget-file. [root@localhost 14_4]# bash substituteStr.sh "YOU" "you" test.txt I like you but JUST like you 狗肉汤就是用狗肉炖成的汤 rr wrr source_hash desternation_hash #lc wlc sed nq lblc lblcr [root@localhost 14_4]# bash substituteStr.sh YOU you test file does not exits.
实例3:检查目录中所有二进制文件的来源的脚本:checkAuthorship.sh
脚本内容:
root@localhost 14_4]# cat checkAuthorship_2.sh #!/bin/bash #此脚本用于在指定目录中找含有特定字符串的二进制文件 # 检查传入参数是否为空,如果为空,打印使用方法,并退出 if [ $# != 2 ] then echo "Usage:`basename $0` target_dir string." exit 1 fi # 检查指定目录是否存在 if [ -d "$1" ] then # 如果指定目录存在,则继续 Dir="$1" else echo "Dir $1 does not exits." exit 2 fi fstring=$2 for file in `find $Dir -type f -name '*' | sort` do strings -f $file | grep "$fstring" | sed -e "s#$Dir##" #cat $file | grep "$fstring" | sed -e "s#$Dir##" done exit 0
执行结果:
[root@localhost 14_4]# bash checkAuthorship_2.sh //参数不全 Usage:checkAuthorship_2.sh target_dir string. [root@localhost 14_4]# bash checkAuthorship_2.sh /mnt/test/shell/s/ //参数不全 Usage:checkAuthorship_2.sh target_dir string. [root@localhost 14_4]# bash checkAuthorship_2.sh /mnt/test/shell/s/ YOU //目录不存在 Dir /mnt/test/shell/s/ does not exits. [root@localhost 14_4]# bash checkAuthorship_2.sh /mnt/test/shell/sed/ YOU 14_4/test.txt: I like YOU but JUST like you output.txt: I like YOU but just LIKE he 1 test2.txt: I like YOU but just LIKE you 1 test.txt: I like YOU but just LIKE you
从sed输出中设置shell变量
实例1:批量修改文件名脚本:rebane.sh
脚本内容:
[root@localhost 14_4]# cat rename.sh #!/bin/bash # 此脚本用来批量重命名当前目录下所有文件 ARGS=2 ONE=1 # 检查传递给脚本的参数个数,如果不为2,打印使用方法并退出 if [ $# -ne "$ARGS" ] then echo "Usage: `basename $0` old-pattern new-pattern" exit 2 fi number=0 # 循环遍历当前目录下所有文件名包含的字符串$1的文件 for filename in *$1* do # 如果指定的文件存在 if [ -f $filename ] then # 出除文件路径 fname=`basename "$filename"` # 用新文件名替换旧文件名 newname=`echo $filename | sed -e "s/$1/$2/g"` # 将文件重命名 mv "$fname" "$newname" let "number += 1" fi done # 使用正确的语法 if [ "$number" -eq "$ONE" ] then echo "$number file renamed" else echo "$number files renamed" fi exit 0
执行结果:
[root@localhost 14_4]# touch fsx{1..3} [root@localhost 14_4]# bash rename.sh Usage: rename.sh old-pattern new-pattern [root@localhost 14_4]# bash rename.sh fsx coco 3 files renamed [root@localhost 14_4]# ls coco* coco1 coco2 coco3
总结
-
sed是用来解析和转换文本的工具。使用简单,是简介的程序设计语言。
-
sed时由贝尔实验室的李E.麦克马洪在1973年~1974年开发的,并且在大部分操作系统上可以使用
-
sed是非交互式的面向数据流的编辑器
使用sed可以做如下操作:
-
自动化编辑一个或多个文件
-
简化在多个文件中执行相同编辑的任务
-
编写转换程序
-
sed维护一种模式空间,即一个工作区或者临时缓冲区,当使用编辑命令时,将在那里存储单个输入行。
-
sed一次处理一行输入,这使得在读取非常庞大的文件时不会出现内存溢出问题。
-
sed命令的两种语法分别如下
sed [OPTIONS]... 'COMMAND' [FILE]... sed [OPTIONS] -f scriptfile [FILE]...
-
sed常用选项:
-
-e:告诉sed将下一个参数解释为sed指令,只有在命令行上给出多个sed指令才需要使用-e选项
-
-f:指定由sed指令组成的脚本名称。如果sed脚本的第一行位"#n",则sed的行为与指定-n选项相同
-
-i:直接修改读取的内容,而不是输出到终端
-
-n:取消默认输出;一般情况下,sed处理后整个文件内容都会输出到终端,但是使用-n后,只由经过sed处理的行才会被显示出来
-
-
在sed中,符号"$"用于只是输出文件中的最后一行或行尾(正则表达)。sed不能直接访问SHELL中的变量,所以必须使用双引号来扩展shell变量。
-
LHS和RHS分别指sed指令汇总的左侧部分和右侧部分。如:替换编辑命令"s/LHS/RHS/"。