码迷,mamicode.com
首页 > 其他好文 > 详细

sed匹配第N个进行替换

时间:2018-12-04 15:35:20      阅读:522      评论:0      收藏:0      [点我收藏+]

标签:ado   elk   全局替换   功能   方法   大括号   http   字符串   文本   

sed -s ‘/^c/{:a;n;s@/bin/bash@/sbin/nologin0@g;/^m/!ba}‘ passwd

[root@elk 13_bash]# cat passwd
a:x:1002:1002::/home/a:/bin/bash
b:x:1003:1003::/home/b:/bin/bash
c:x:1004:1004::/home/c:/bin/bash
d:x:1005:1005::/home/d:/bin/bash
e:x:1006:1006::/home/e:/bin/bash
f:x:1007:1007::/home/f:/bin/bash
g:x:1008:1008::/home/g:/bin/bash
h:x:1009:1009::/home/h:/bin/bash
j:x:1010:1010::/home/j:/bin/bash
k:x:1011:1011::/home/k:/bin/bash
l:x:1012:1012::/home/l:/bin/bash
m:x:1013:1013::/home/m:/bin/bash
n:x:1014:1014::/home/n:/bin/bash
p:x:1015:1015::/home/p:/bin/bash
i:x:1016:1016::/home/i:/bin/bash
cc:x:1017:1017::/home/cc:/bin/bash
dd:x:1018:1018::/home/dd:/bin/bash
ee:x:1019:1019::/home/ee:/bin/bash
bb:x:1020:1020::/home/bb:/bin/bash
[root@elk 13_bash]# sed -s ‘/^c/{:a;n;s@/bin/bash@/sbin/nologin0@g;/^m/!ba}‘ passwd
a:x:1002:1002::/home/a:/bin/bash
b:x:1003:1003::/home/b:/bin/bash
c:x:1004:1004::/home/c:/bin/bash
d:x:1005:1005::/home/d:/sbin/nologin0
e:x:1006:1006::/home/e:/sbin/nologin0
f:x:1007:1007::/home/f:/sbin/nologin0
g:x:1008:1008::/home/g:/sbin/nologin0
h:x:1009:1009::/home/h:/sbin/nologin0
j:x:1010:1010::/home/j:/sbin/nologin0
k:x:1011:1011::/home/k:/sbin/nologin0
l:x:1012:1012::/home/l:/sbin/nologin0
m:x:1013:1013::/home/m:/sbin/nologin0
n:x:1014:1014::/home/n:/bin/bash
p:x:1015:1015::/home/p:/bin/bash
i:x:1016:1016::/home/i:/bin/bash
cc:x:1017:1017::/home/cc:/bin/bash
dd:x:1018:1018::/home/dd:/sbin/nologin0
ee:x:1019:1019::/home/ee:/sbin/nologin0
bb:x:1020:1020::/home/bb:/sbin/nologin0
[root@elk 13_bash]#

技术分享图片
怎么匹配开头c到开头m(开始结束字符串确定),然后替换/bin/bash为/sbin/nologin0这样的
先匹配开头c,匹配到后执行大括号里的语句。
n 读取下一行
s@/bin/bash@/sbin/nologin0@g 将/bin/bash替换为/sbin/nologin0,全局替换,同一行中出现几次替换几次
:a 设定跳转标签a
/^m/!ba 若当前行匹配不上开头m,则跳转到标签a处继续执行,构成一个循环。若匹配到开头f,则退出循环,sed重新对读入的每行匹配开头c。
由于sed没有加-n静默选项,所以默认对每行数据处理后都打印。
其中:a和!ba中的a是可以随意改变的,其中的b是不可改变的.


例:转载于:http://blog.uouo123.com/post/704.html
文本内容:
aa
88
bb
88
88
cc
88
88
替换第一个88为--:
sed ‘0,/88/s//--/‘ file
sed ‘:a;N;$!ba;s/88/--/‘ file

[解析] 这有两种方法,
第一个是只匹配到第一个88为止,然后替换那个88为--。
第二个句子是通过循环把文本全部读进pattern space 然后只替换第一个。
替换第N[3]个88为--:
sed ‘/88/{x;s/^/./;/^.{3}$/{x;s/./--/;x};x;}‘ file
sed ‘:a;N;$!ba;s/88/--/3‘ file
[解析]
第一个命令叫打点记数法,因为sed没有 var++ 之类的操作来记数。
第二个命令和上面第一个其实是一样的原理,全部读入文本后统一替换第3个匹配的内容。
替换最后一个匹配的88为--:
sed ‘:a;/\n88/!{$s/88/--/;N;ba};P;D‘ file
sed ‘:a;N;$!ba;s/(.
)88/\1--/‘ file

[解析]
第一个命令,没匹配到 /\n88/ 的内容就读取下一行,然后 ba 跳转去开始处,如果读取到88的行呢,就执行后面的 P;D 组合,D也有循环功能,一直把匹配 \n88 内容的第一行打印,删除,直到不匹配/\n88/(因为换行符已经被打印出去了,所以不再会匹配到 \n88),这时候才继续往下读,如果又读到88的行,那么又执行P;D循环,同上操作。一直到匹配到最后一个88的行,继续读取到末行时执行替换,N 因为没有下一行可读,所以会自动中止命令,因为没有 -n 参数会打印 pattern space 里的内容到屏幕,所以就不会再执行后面的 ba 避免了死循环,这样的用法只存在于 GNU sed ,大家注意。所以这整个流程只会替换最后一个88。
第二个命令其实和上面的都一样,也是全部读进 pattern space 里,最后利用正则的贪婪替换掉最后一个88。

sed匹配第N个进行替换

标签:ado   elk   全局替换   功能   方法   大括号   http   字符串   文本   

原文地址:http://blog.51cto.com/chier11/2325912

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!