三剑客之sed
Posted xiaofeiweb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三剑客之sed相关的知识,希望对你有一定的参考价值。
sed
Stream EDitor
流编辑器,逐行过滤和替换文本
默认不编辑源文件,仅对模式空间中的数据做处理,处理结束后,将模式空间输出至屏幕
工作原理
sed命令将当前处理的行读入自己的模式空间(pattem space)进行处理,处理完把结果打印至屏幕,并清空模式空间,然后再将下一行读入模式空间进行处理输出,以此类推,直到最后一行.
还有一个空间叫保持空间,又称暂存空间,可以暂时存放一些处理的数据,但不能直接输出,只能放到模式空间输出.
这两个空间其实就是在内存中初始化的一个内存区域,存放正在处理的数据和临时存放的数据.
使用格式
sed [OPTIONS]... ‘script‘ inputfile...
sed OPTIONS ‘/PATTERN/COMMAND‘ FILE_NAME
地址定界符
单地址
n: 指定的行(n为数字)
/pattern/: 被此处模式所能够匹配到每一行
地址范围
m,n: 从m到n行
m,+n: 从第m行到往后n行
/pat1/,/pat2/: 表示从第一次匹配pattern1模式的行开始,到第一次匹配pattern2模式的行结束,取中间所有的行
m,/pat1/: 从第m行到第一次匹配到pat1
$: 表示最后一行# 删除第二行 sed ‘2d‘ file # 删除第二行到最后一行 sed ‘2,$d‘ file # 删除最后一行 sed ‘$d‘ file # 删除文件中以test开头的行 sed ‘/^test/‘d file
常用选项(option)
-n: 静默模式,不打印模式空间内的内容
-e script: 多点编辑,允许在同一行里执行多条命令,使用分号;隔开
sed -e ‘1,5d‘ -e ‘s/test/check/‘ file # 注: 上面sed表达式的第一条命令删除1至5行,第二条命令用check替换test。命令的执行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果 # 和 -e 等价的命令是 --expression: sed --expression=‘s/test/check/‘ --expression=‘/love/d‘ file
-f file: 从指定文件file中读取编辑脚本
sed [options] -f scriptfile file(s) # sed脚本是一个sed的命令清单,启动Sed时以-f选项引导脚本文件名。Sed对于脚本中输入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多个命令,要用分号分隔。以#开头的行为注释行,且不能跨行
-r: 支持使用扩展正则表达式
-i: 直接修改原文件(此操作有风险)
处理命令(command)
多个处理命令,使用分号;隔开
p: 打印模式空间中的内容,仅打印符合条件的内容,一般配合-n来使用
# 显示/etc/fstab中以/开头的行,/为特殊符号,需转义 sed -n ‘/^\//p‘ /etc/fstab
d: 删除符合条件的行(模式空间中的行)
# 删除文件/etc/fstab中第一行,把剩下的内容显示到屏幕上,原文件内容不会发生任何改变 sed ‘1d‘ /etc/fstab # 删除带有oot的行,如果匹配字符串,需要用/隔开 sed ‘/oot/d‘ /etc/fstab
a \‘text‘: 在行后面追加文本,支持使用\n换行符实现多行追加
i \‘text‘: 在行前面插入文本,支持使用\n换行符实现多行插入
c \‘text‘: 替换符合条件的行为单行或多行文本
w /path/to/somefile: 保存模式空间中的内容至指定文件中
r /path/from/somefile: 读取指定文件的文本流至模式空间中的行后
# 将文件/etc/fstab中包含有oot的行另存至文件/tmp/oot.txt文件中 sed ‘/oot/w /tmp/oot.txt‘ /etc/fstab # 把/etc/issue文件的内容添加到/etc/fstab文件内容第二行的后面 sed ‘2r /etc/issue‘ /etc/fstab
=: 显示符合条件的行的行号,为模式空间中的行打印行号
D: 删除多行模式空间中的所有行
h: 把模式空间中的内容覆盖至保持空间中
H: 把模式空间中的内容追加至保持空间中
g: 从保持空间取出数据并覆盖至模式空间中
G: 从保持空间取出内容并追加至模式空间中
x: 把模式空间中的内容与保持空间中的内容进行互换
n: 读取匹配到的行的下一行至模式空间
N: 追加匹配到的行的下一行至模式空间
cat test.txt """ 1 2 3 4 5 6 """ # 逆序显示文本内容 sed ‘1!G;h;$!d‘ test.txt """ 说明: 读第一行,将第一行读取到自己的模式空间中: 1!G是指除了第一行,其他行都从保持空间取出并追加至模式空间中,那么第一行不会追加; h是把模式空间中的第一行数据覆盖至保持空间中,此时保持空间中有了第一行数据,此时,模式空间和保持空间都有了第一行数据; $!d是指除了最后一行都删除,那么模式空间中的数据不是最后一行,则执行后面删除操作 读第二行至模式空间中: 先从保持空间中取出第一行的数据,追加到模式空间中,此时模式空间中有了第二行数据和第一行数据,然后执行h,模式空间中的内容覆盖至保持空间中,此时保持空间中的数据从上到下,有了第二行数据,第一行数据,最后判断是否为最后一行,否则删除; 以此类推,当读取到最后一行数据至模式空间中: 此时的模式空间中存在的是最后一行数据,而保持空间中按从上到下顺序应该是:倒数第二行数据,倒数第三行数据,...,然后执行G,从保持空间取出内容并追加至模式空间中,此时的模式空间中的数据则形成了倒序的方式,然后执行h,把模式空间中的内容覆盖至保持空间中,此时模式和保持空间的数据都是以倒序的方式存放的数据,最后判断是否为最后一行,很明显是最后一行,那么就不会再执行删除操作 最后打印出模式空间中的内容 """ # 取出最后1行 sed ‘$!d‘ /etc/passwd # 取出最后2行 sed ‘$!N;$!D‘ /etc/passwd # 每一行后面追加一个空白行 sed ‘G‘ /etc/passwd # 全部替换成空白行 sed ‘g‘ /etc/passwd # 显示偶数行 sed -n ‘n;p‘ test.txt # 显示奇数行 sed ‘n;d‘ /etc/passwd # 删除原有的所有空白行,而后为所有的非空白行后添加一个空白行 sed ‘/^$/d;G‘ /etc/passwd # 删除原有的所有空白行,而后为所有的非空白行后添加一个空白行 sed ‘/^$/d;G‘ /etc/passwd # 显示最后一行的行号,一般可用于显示文本的总行 sed -n ‘$=‘ /etc/fstab # 显示所有行的行号,但空行不显示行号 sed ‘/./=‘ /etc/fstab
s/old/new/: 查找替换,替换old为new,其中/可以自定义,比如也可以写成[email protected]@@,s###等
替换标记:
g: 行内全局替换(s///g),即替换所有匹配到的字符串
p: 显示替换成功的行(s///p)
w FILE: 将替换成功的结果保存至文件中
i: 忽略字符大小写
&: 表示引用匹配到的内容
!: 取反条件
\w+ 匹配每一个单词
示例
# 查找文件sftab含有oot的行全部替换成OOT,默认只替换每行第一次被模式匹配到的串 sed ‘s/oot/OOT/‘ /etc/fstab # 查找文件fstab中,/开头的字符串,把/全部换成*号 sed ‘s/^\//*/g‘ /etc/fstab 表示 # 符合l..e模式的字符串,在后面添加一个er sed ‘[email protected]@&[email protected]‘ /etc/fstab sed ‘s#\(l..e\)#\1er#g‘ /etc/fstab # 将每个单词使用方括号[]括起来 echo ‘this is a test line‘ | sed ‘s/\w\+/[&]/g‘ """ [this] [is] [a] [test] [line] ""‘ # 替换‘digit 7‘为‘6‘ echo ‘this is digit 7 in number.‘ | sed ‘[email protected] \([0-9]\)@\[email protected]‘ # 查找/etc/fstab文件中,UUID和tmpfs之间的行,每行的行尾加上字符串aaa bbb sed ‘/UUID/,/tmpfs/[email protected][email protected] [email protected]‘ /etc/fstab # 查找line1到line2之间的所有aa bbb 替换为AA BBB sed ‘/line1/,/line2/[email protected] [email protected] [email protected]‘ file_name # 显示第一次匹配到的3,到最后一行输出 sed -n ‘/3/,$p‘ file_name # 显示第一次匹配到的3,到向下2行输出 sed -n ‘/3/,+2p‘ file_name
注:
所有的处理命令均是在sed自己的模式空间内操作
要想同步修改目标文件内容,需要加上-i选项
练习题
# 删除/boot/grub/grub.conf文件中所有以空白开头的行的行首的空白字符 sed ‘s#^[[:space:]]\+##‘ /boot/grub/grub.confsed # 删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符 sed ‘[email protected]^#[[:space:]]\[email protected]@‘ /etc/fstab # echo一个绝对路径给sed命令,取出其基名,取出其目录名 echo ‘/etc/sysconfig/network‘ | sed ‘[email protected][^/]\+/\[email protected]@‘ # 删除文件/etc/init.d/inittab中所有的数字 sed ‘s/[[:digit:]]\+//g‘ /etc/init.d/inittab # 将时间格式 yy/mm/dd 的日期格式换成 yy:mm:dd的格式 date +"%Y/%m/%d" |sed -n ‘s#/#:#gp‘ # 显示奇数行 sed -n ‘1~2p‘ file_name # 显示偶数行 sed -n ‘2~2p‘ file_name # 删除模式一到模式二匹配到的行 sed ‘/^aaa/,/^eee/d‘ file_name # 从指定行开始开始,每隔2行显示一次 sed -n ‘2,${p;n;n}‘ file_name # 删除一个文件中所有的数字 sed ‘s/[[:digit:]]\+//g‘ /etc/init.d/inittab # 将时间格式 yy/mm/dd 的日期格式换成 yy:mm:dd的格式 date +"%Y/%m/%d" |sed -n ‘s#/#:#gp‘ # 显示奇数行 sed -n ‘1~2p‘ file # 删除模式一到模式二匹配到的行 sed ‘/^aaa/,/^eee/d‘ File # 从指定行开始开始,每隔2行显示一次 sed -n ‘2,${p;n;n}‘ File # 删除文中的最后两行 sed ‘N;$!P;$!D;$d‘ /etc/passwd # 删除文中的空行 sed ‘/./!d‘ /etc/fstab # 每隔5行增加一个空行 sed ‘n;n;n;n;G;‘ File # 不显示指定字符开始的行 sed -n ‘/^aaa\+/!p‘ File # 查找文件中1到20行之间,同时将”aaa”替换为”AAA” ,”ddd”替换”DDD” sed -nr ‘s/(.*)([^a-Z]+)([a-Z]+)([^a-Z]*)/\1\2\4/p‘ /etc/passwd # 替换文本中的字符串 echo "sksksksksksk" | sed ‘s/sk/SK/3g
cat test """ 1 nimgtw 48003/udp # Nimbus Gateway 2 3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol 3 isnetserv 48128/tcp # Image Systems Network Services 4 isnetserv 48128/udp # Image Systems Network Services 5 blp5 48129/tcp # Bloomberg locator 6 blp5 48129/udp # Bloomberg locator 7 com-bardac-dw 48556/tcp # com-bardac-dw 8 com-bardac-dw 48556/udp # com-bardac-dw 9 iqobject 48619/tcp # iqobject 10 iqobject 48619/udp # iqobject """ # 打印匹配‘blp5‘开头的行 sed -n ‘/^blp5/p‘ test # 打印出第一行 sed -n ‘1p‘ test # 打印出第1行到第3行 sed -n ‘1,3p‘ # 打印出奇数行 sed -n ‘1~2p‘ test # 打印出偶数行 sed -n ‘2~2p‘ test # 打印匹配的行和它后面的一行 sed -n ‘/nimgtw/,+1p‘ test # 打印最后一行 sed -n ‘$p‘ test # 打印所有行,除了最后一行 sed -n ‘$!p‘ test # 匹配范围 sed -n ‘/^blp5/,/^com/p‘ test # 匹配开头行到最后一行 sed -n ‘/^blp5/,$p‘ test # 引用变量,来匹配行 a = 1 sed -n ‘‘$a‘,3p‘ test # 注意:sed后面跟单引号,变量需要单引号才能引用,sed后面用双引号,变量则无需引号也会被引用 # 匹配删除 sed ‘/blp5/d‘ test # 匹配删除奇数行 sed ‘1~2d‘ test # 匹配删除第1行到第3行 sed ‘1,3d‘ test # 替换blp5为test sed ‘s/blp5/test/g‘ test # 替换开头是blp5的行并打印 sed -n ‘s/^blp5/test/p‘ test # 引用匹配内容并替换 sed ‘s/^blp5/&00000000/‘ test # ip加单引号 echo ‘10.10.10.1 10.10.10.2 10.10.10.3‘ | sed -r ‘s/[^ ]+/"&"/g‘ # 对1-5行的blp5进行替换 sed ‘1,5s/blp5/test/‘ test # 对匹配行进行替换,查找tcp且开头是com的行,替换成COM sed ‘/tcp/s/^com/COM/‘ test # 多次匹配并替换 sed ‘s/blp5/test/;s/3g/4g/‘ test # 将协议与端口号位置调换(不明白) sed -r ‘s/(.*)(\<[0-9]+\>)\/(tcp|udp)(.*)/\1\3\/\2\4/‘ test # 注释掉匹配行后面的指定行数 seq 10 | sed ‘/5/,+3s/^/#/‘
# 将 error.log中匹配到的内容保存至某个文件中: sed -n ‘/root/w file.txt‘ error.log # 将文件中的内容读入到匹配的内容后面 sed ‘/root/r abc.txt‘ /etc/passwd # 打印匹配到的内容,并显示行号 sed -n ‘/root/{=;p}‘ /etc/passwd # 删除匹配到的行的下一行 sed -n ‘/UUID/{n;d}‘ /etc/fstab # 删除匹配到的行和下一行 sed ‘/UUID/{N;d}‘ /etc/fstab # 删除文件每行中的第一个字符 sed -n ‘s/^.//gp‘ /etc/fstab # 删除文件每行的第二个字符 sed -nr ‘s/(.)(.)(.*)/\1\3/p‘ /etc/passwd # 删除文件每行的最后一个字符 sed -nr ‘s/.$//p‘ /etc/passwd # 删除每行的最后一个单词 sed -nr ‘s/(.*)([^a-Z]+)([a-Z]+)([^a-Z]*)/\1\2\4/p‘ /etc/passwd # 将file文件中的内容,实现最终效果,如下: cat file """ aaa bbb ccc ddd eee fff ggg hhh """ # 实现如下效果: cat file """ aaa bbb ccc ddd eee fff ggg hhh """ # 实现方法 sed ‘N;s/\n/\t/‘ b.tx # 实现原理: # N:读取下一行并追加到模式空间中的行后面,当Sed读入第一行内容时,由N将下一行的内容追加到模式空间中,此时模式空间的内容为“aaa\nbbb”,再由编写的匹配规则进行替换将”\n”替换为了”\t”,再执行默认的”p”操作,输出到标准输出