Linux sed实战

目录

一、替换

1、全局替换shell中的某个字符。

2、正则匹配空行并删除  

3、替换经典案例(正则)

4、时间处理

5、滤出html中href 元素后的网址

6、替换匹配到的字符串

7、忽略大小写替换

​编辑

8、匹配到的行整行替换

二、查找

1、查找匹配到的行

三、修改行

1、给不需要的行添加注释

2、 删除奇数、偶数行

3、在行中任意位置添加内容

--update 2022年6月23日14:56:52

批量重命名文件

 4、sed -r 读取外部文件

 5、匹配到的行写入其他文件 

 6、模式空间中的a i c

​编辑

 7、-n 隔山打牛

多行命令

 8、sed -h -H 和-g -G 写入

9、sed对广义空行的处理

10、sed修改ssh配置

11、sed使用外部变量

 12、sed实现字符串倒转

三、统计

3.1 怎么检查一个文本文件中某一行的长度?

四、修改文本

4.1 如何向文本指定位置插入另外一个文本?

五、统计某行中包含数字的个数

六、sed 和正则搭配使用

分离数组和字母

格式化数字串

打印序号

打印末尾行

去掉字符串中的引号


一、替换

查找并替换时,sed中分隔符号不一定要使用/ ,可以使用@ #,仅当查找时不能使用其他分隔符

例如

[root@ninesun example]# cat -n a.log 
     1	dsd
     2	/etc/hosts
     3	
[root@ninesun example]# sed -r 's#/etc/hosts#/var/lib/hosts#g' a.log 
dsd
/var/lib/hosts

1、全局替换shell中的某个字符。

需要使用 -i参数才会真正修改文件,该操作不会再屏幕上返回结果。

匹配test.sh中的vmstatGene行,并将vmstatGene_169全局替换为vmstatGene_122,末尾不加g则替换第一次出现匹配关键字的位置。

sed -i '/vmstatGene/s@vmstatGene_169@vmstatGene_122@g' test.sh

ansible 替换crontab文件中关键字。可以结合管道操作匹配到的多个文件, 

例如find match到多个shell

[root@gptest01 scripts]# find /home/scripts/ -type f -path "*.sh"
/home/scripts/formatVmstat_start.sh
/home/scripts/redis/insertJgeCnt.sh
/home/scripts/redis/evaluateMem.sh
/home/scripts/redis/evaluateHisOpeMem.sh
/home/scripts/redis/evaluateResult.sh
/home/scripts/redis/insertHistory.sh
/home/scripts/redis/insertResult.sh
/home/scripts/redis/del.sh
/home/scripts/redis/inersertOpehisKey.sh
/home/scripts/redis/istAll.sh
/home/scripts/formatVmstat_eth0.sh
/home/scripts/formatVmstat_bond1.sh
/home/scripts/formatVmstat_bak.sh

ansibe 批量替换

[root@gptest01 scripts]# ansible 10.50.10.172 -m shell -a  "find /var/spool/cron -name "root"|xargs sed -i '/vmstat_1/s@vmstat_172@vmstatGene_172@'"

[root@gptest01 scripts]# ansible 10.50.10.173 -m shell -a  "time sed -i '/vmstat_1/s@vmstat_173@vmstatGene_173@' /var/spool/cron/root"

2、正则匹配空行并删除  

删除空白行。

sed  '/^$/p' gpdb-2020-05-23_000000.csv 
2020-05-23 21:56:14.524927 CST,"gpadmin","qmstst",p2588,th-625846464,"[local]",,2020-05-23 21:56:14 CST,0,,,seg-1,,,,sx1,"WARNING","01000","time constraints added on superuser role",,,,,,,0,,"auth.c",2966,
2020-05-23 21:56:14.525134 CST,"gpadmin","qmstst",p2588,th-625846464,"[local]",,2020-05-23 21:56:14 CST,0,,,seg-1,,,,sx1,"FATAL","3D000","database ""qmstst"" does not exist",,,,,,,0,,"postinit.c",956,
2020-05-23 21:56:22.618282 CST,"gpadmin","postgres",p2975,th-625846464,"[local]",,2020-05-23 21:56:22 CST,0,,,seg-1,,,,sx1,"WARNING","01000","time constraints added on superuser role",,,,,,,0,,"auth.c",2966,
2020-05-23 21:56:22.619526 CST,"gpadmin","postgres",p2975,th-625846464,"[local]",,2020-05-23 21:56:22 CST,0,,,seg-1,,,,sx1,"FATAL","57P03","System was started in master-only utility mode - only utility mode connections are allowed",,,,,,,0,,"postinit.c",1142,




[root@gptest01 pg_log]# sed  '/^$/d' gpdb-2020-05-23_000000.csv 
2020-05-23 21:56:14.524927 CST,"gpadmin","qmstst",p2588,th-625846464,"[local]",,2020-05-23 21:56:14 CST,0,,,seg-1,,,,sx1,"WARNING","01000","time constraints added on superuser role",,,,,,,0,,"auth.c",2966,
2020-05-23 21:56:14.525134 CST,"gpadmin","qmstst",p2588,th-625846464,"[local]",,2020-05-23 21:56:14 CST,0,,,seg-1,,,,sx1,"FATAL","3D000","database ""qmstst"" does not exist",,,,,,,0,,"postinit.c",956,
2020-05-23 21:56:22.618282 CST,"gpadmin","postgres",p2975,th-625846464,"[local]",,2020-05-23 21:56:22 CST,0,,,seg-1,,,,sx1,"WARNING","01000","time constraints added on superuser role",,,,,,,0,,"auth.c",2966,
2020-05-23 21:56:22.619526 CST,"gpadmin","postgres",p2975,th-625846464,"[local]",,2020-05-23 21:56:22 CST,0,,,seg-1,,,,sx1,"FATAL","57P03","System was started in master-only utility mode - only utility mode connections are allowed",,,,,,,0,,"postinit.c",1142,

3、替换经典案例(正则)

要点: sed 结合正则替换一个和多个空格.

 替换前是这样的:

go_gc_duration_seconds{quantile="0"} 0.000158734
go_gc_duration_seconds{quantile="0.25"} 0.000242638
go_gc_duration_seconds{quantile="0.5"} 0.000272045
go_gc_duration_seconds{quantile="0.75"} 0.000311615
go_gc_duration_seconds{quantile="1"} 0.005289956
go_gc_duration_seconds_sum 72.816662569
go_gc_duration_seconds_count 221774
go_goroutines 12
go_memstats_alloc_bytes 1.07251032e+08
go_memstats_alloc_bytes_total 9.151138705928e+12

替换后:

192.168.200.23|2020-06-25 19:22:09|go_gc_duration_seconds{quantile="0"}|0.000158734
192.168.200.23|2020-06-25 19:22:09|go_gc_duration_seconds{quantile="0.25"}|0.000242638
192.168.200.23|2020-06-25 19:22:09|go_gc_duration_seconds{quantile="0.5"}|0.000272045
192.168.200.23|2020-06-25 19:22:09|go_gc_duration_seconds{quantile="0.75"}|0.000311615
192.168.200.23|2020-06-25 19:22:09|go_gc_duration_seconds{quantile="1"}|0.005289956
192.168.200.23|2020-06-25 19:22:09|go_gc_duration_seconds_sum|72.816662569
192.168.200.23|2020-06-25 19:22:09|go_gc_duration_seconds_count|221774
192.168.200.23|2020-06-25 19:22:09|go_goroutines|12
192.168.200.23|2020-06-25 19:22:09|go_memstats_alloc_bytes|1.07251032e+08
192.168.200.23|2020-06-25 19:22:09|go_memstats_alloc_bytes_total|9.151138705928e+12

 这是为了将非结构化的数据转换为结构化的数据并将其持久化到数据库。

先看一下这个例子

rabbmitMq]# cat tst.log |sed 's/ /|/'|awk '{print strftime("%Y-%m-%d %H:%M:%S"),$0}'|sed 's/[ ][ ]*/|/g'|head
2020-06-25|22:23:20|go_gc_duration_seconds{quantile="0"}|0.000158734
2020-06-25|22:23:20|go_gc_duration_seconds{quantile="0.25"}|0.000242638
2020-06-25|22:23:20|go_gc_duration_seconds{quantile="0.5"}|0.000272045
2020-06-25|22:23:20|go_gc_duration_seconds{quantile="0.75"}|0.000311615
2020-06-25|22:23:20|go_gc_duration_seconds{quantile="1"}|0.005289956
2020-06-25|22:23:20|go_gc_duration_seconds_sum|72.816662569
2020-06-25|22:23:20|go_gc_duration_seconds_count|221774
2020-06-25|22:23:20|go_goroutines|12
2020-06-25|22:23:20|go_memstats_alloc_bytes|1.07251032e+08
2020-06-25|22:23:20|go_memstats_alloc_bytes_total|9.151138705928e+12

可以看到时间的空格那里也被|隔开,是我们不想要的。如何处理这个时间格式中的空格呢?

这里采用一种迂回的方式来完成。

's/|/ /' 替换每行首个|为空格,即完成了需求。

~]# cat /home/scripts/tune/rabbmitMq/tst.log |sed 's/ /|/'|awk '{print strftime("%Y-%m-%d %H:%M:%S"),$0}'|sed 's/[ ]/|/g'|sed 's/|/ /'|head
2020-06-26 10:35:28|go_gc_duration_seconds{quantile="0"}|0.000158734
2020-06-26 10:35:28|go_gc_duration_seconds{quantile="0.25"}|0.000242638
2020-06-26 10:35:28|go_gc_duration_seconds{quantile="0.5"}|0.000272045
2020-06-26 10:35:28|go_gc_duration_seconds{quantile="0.75"}|0.000311615
2020-06-26 10:35:28|go_gc_duration_seconds{quantile="1"}|0.005289956
2020-06-26 10:35:28|go_gc_duration_seconds_sum|72.816662569
2020-06-26 10:35:28|go_gc_duration_seconds_count|221774
2020-06-26 10:35:28|go_goroutines|12
2020-06-26 10:35:28|go_memstats_alloc_bytes|1.07251032e+08
2020-06-26 10:35:28|go_memstats_alloc_bytes_total|9.151138705928e+12

最后再把ip 添加到行首或者行尾即可。

~]# cat /home/scripts/tune/rabbmitMq/tst.log |sed 's/ /|/'|awk '{print strftime("%Y-%m-%d %H:%M:%S"),$0}'|sed 's/[ ][ ]*/|/g'|sed 's/|/ /'|sed 's/^/'192.168.200.23'|/g'|head -n 10
192.168.200.23|2020-06-26 10:41:35|go_gc_duration_seconds{quantile="0"}|0.000158734
192.168.200.23|2020-06-26 10:41:35|go_gc_duration_seconds{quantile="0.25"}|0.000242638
192.168.200.23|2020-06-26 10:41:35|go_gc_duration_seconds{quantile="0.5"}|0.000272045
192.168.200.23|2020-06-26 10:41:35|go_gc_duration_seconds{quantile="0.75"}|0.000311615
192.168.200.23|2020-06-26 10:41:35|go_gc_duration_seconds{quantile="1"}|0.005289956
192.168.200.23|2020-06-26 10:41:35|go_gc_duration_seconds_sum|72.816662569
192.168.200.23|2020-06-26 10:41:35|go_gc_duration_seconds_count|221774
192.168.200.23|2020-06-26 10:41:35|go_goroutines|12
192.168.200.23|2020-06-26 10:41:35|go_memstats_alloc_bytes|1.07251032e+08
192.168.200.23|2020-06-26 10:41:35|go_memstats_alloc_bytes_total|9.151138705928e+12

总结: 

  • s
  • 使用替换模式替换相应模式
  • []
  • 匹配指定范围内的任意单个字符
  • *
  • 匹配紧挨在前面的字符任意次(0,1,多次)
  •  's/[ ][ ]*/|/g' 
  • 开启匹配模式,匹配一个空格或N个空格全局替换为 | 
  •  's/|/ /'

替换每行首个|为空格 

有人想说匹配一个或N个空格为什么不直接用 s/[ ]*/|/g 呢?请看下例,可以看到如果直接使用这个表达式将0个空格的情况也包含了。

rabbmitMq]# cat tst.log |sed 's/ /|/'|awk '{print strftime("%Y-%m-%d %H:%M:%S"),$0}'|sed 's/[ ]*/|/g'|head
|2|0|2|0|-|0|6|-|2|5|2|2|:|2|8|:|0|2|g|o|_|g|c|_|d|u|r|a|t|i|o|n|_|s|e|c|o|n|d|s|{|q|u|a|n|t|i|l|e|=|"|0|"|}|||0|.|0|0|0|1|5|8|7|3|4|
|2|0|2|0|-|0|6|-|2|5|2|2|:|2|8|:|0|2|g|o|_|g|c|_|d|u|r|a|t|i|o|n|_|s|e|c|o|n|d|s|{|q|u|a|n|t|i|l|e|=|"|0|.|2|5|"|}|||0|.|0|0|0|2|4|2|6|3|8|
|2|0|2|0|-|0|6|-|2|5|2|2|:|2|8|:|0|2|g|o|_|g|c|_|d|u|r|a|t|i|o|n|_|s|e|c|o|n|d|s|{|q|u|a|n|t|i|l|e|=|"|0|.|5|"|}|||0|.|0|0|0|2|7|2|0|4|5|
|2|0|2|0|-|0|6|-|2|5|2|2|:|2|8|:|0|2|g|o|_|g|c|_|d|u|r|a|t|i|o|n|_|s|e|c|o|n|d|s|{|q|u|a|n|t|i|l|e|=|"|0|.|7|5|"|}|||0|.|0|0|0|3|1|1|6|1|5|
|2|0|2|0|-|0|6|-|2|5|2|2|:|2|8|:|0|2|g|o|_|g|c|_|d|u|r|a|t|i|o|n|_|s|e|c|o|n|d|s|{|q|u|a|n|t|i|l|e|=|"|1|"|}|||0|.|0|0|5|2|8|9|9|5|6|
|2|0|2|0|-|0|6|-|2|5|2|2|:|2|8|:|0|2|g|o|_|g|c|_|d|u|r|a|t|i|o|n|_|s|e|c|o|n|d|s|_|s|u|m|||7|2|.|8|1|6|6|6|2|5|6|9|
|2|0|2|0|-|0|6|-|2|5|2|2|:|2|8|:|0|2|g|o|_|g|c|_|d|u|r|a|t|i|o|n|_|s|e|c|o|n|d|s|_|c|o|u|n|t|||2|2|1|7|7|4|
|2|0|2|0|-|0|6|-|2|5|2|2|:|2|8|:|0|2|g|o|_|g|o|r|o|u|t|i|n|e|s|||1|2|
|2|0|2|0|-|0|6|-|2|5|2|2|:|2|8|:|0|2|g|o|_|m|e|m|s|t|a|t|s|_|a|l|l|o|c|_|b|y|t|e|s|||1|.|0|7|2|5|1|0|3|2|e|+|0|8|
|2|0|2|0|-|0|6|-|2|5|2|2|:|2|8|:|0|2|g|o|_|m|e|m|s|t|a|t|s|_|a|l|l|o|c|_|b|y|t|e|s|_|t|o|t|a|l|||9|.|1|5|1|1|3|8|7|0|5|9|2|8|e|+|1|2|

对于本例替换空格可以直接使用  's/[ ]/|/g' 

~]# cat /home/scripts/tune/rabbmitMq/tst.log |sed 's/ /|/'|awk '{print strftime("%Y-%m-%d %H:%M:%S"),$0}'|sed 's/[ ]/|/g'|sed 's/|/ /'|head -n 10
2020-06-26 10:48:14|go_gc_duration_seconds{quantile="0"}|0.000158734
2020-06-26 10:48:14|go_gc_duration_seconds{quantile="0.25"}|0.000242638
2020-06-26 10:48:14|go_gc_duration_seconds{quantile="0.5"}|0.000272045
2020-06-26 10:48:14|go_gc_duration_seconds{quantile="0.75"}|0.000311615
2020-06-26 10:48:14|go_gc_duration_seconds{quantile="1"}|0.005289956
2020-06-26 10:48:14|go_gc_duration_seconds_sum|72.816662569
2020-06-26 10:48:14|go_gc_duration_seconds_count|221774
2020-06-26 10:48:14|go_goroutines|12
2020-06-26 10:48:14|go_memstats_alloc_bytes|1.07251032e+08
2020-06-26 10:48:14|go_memstats_alloc_bytes_total|9.151138705928e+12

这个表达式变得更好理解,但是通用性变差了,如果某个参数和值之间是两个空格呢? 

我修改一下让其中出现两个空格的情况存在。

这个就变成了两个||,解决这个问题的方法就是使用 's/[ ][ ]*/|/'.如下图

这个问题曾经在处理vmstat时遇到过,处理方式和上面的方法是一样的。

4、时间处理

格式化时间是常见的需求,应熟练掌握。

opt]# date '+%Y-%m-%d %H:%M:%S'
2022-01-03 02:27:03

opt]# date '+%Y-%m-%d %H:%M:%S' | sed 's/-//g' | sed 's/ //g' | sed 's/':'//g'
20220103022906

5、滤出html中href 元素后的网址

文本如下

<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10353166.html">Linux性能优化实战学习笔记:第二讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10802102.html">Linux性能优化实战学习笔记:第三讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10808031.html">Linux性能优化实战学习笔记:第五讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10808936.html">Linux性能优化实战学习笔记:第六讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10809642.html">Linux性能优化实战学习笔记:第七讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10811704.html">Linux性能优化实战学习笔记:第八讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10815283.html">Linux性能优化实战学习笔记:第九讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10820252.html">Linux性能优化实战学习笔记:第十讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10592001.html">Linux性能优化实战学习笔记:第十一讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10827212.html">Linux性能优化实战学习笔记:第十二讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10833109.html">Linux性能优化实战学习笔记:第十三讲</a></p>
<h2>&nbsp;二、内存性能:8讲</h2>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10831209.html">Linux性能优化实战学习笔记:第十五讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10832062.html">Linux性能优化实战学习笔记:第十六讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10839790.html">Linux性能优化实战学习笔记:第十七讲</a><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10804753.html"><br></a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10833689.html">Linux性能优化实战学习笔记:第十七讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10842424.html">Linux性能优化实战学习笔记:第十八讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10353819.html">Linux性能优化实战学习笔记:第十九讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10353904.html">Linux性能优化实战学习笔记:第二十讲</a></p>
<p><a class="entrylistItemTitle" href="https://www.cnblogs.com/luoahong/p/10844808.html">Linux性能优化实战学习笔记:第二十一讲</a></p>
<h2>&nbsp;三、IO性能:10讲</h2>

 主要分为两步:

  1. 取出href整个元素
 regExp]# more html_parse.html |awk '{print$3}'
href="https://www.cnblogs.com/luoahong/p/10353166.html">Linux性能优化实战学习笔记:第二讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10802102.html">Linux性能优化实战学习笔记:第三讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10808031.html">Linux性能优化实战学习笔记:第五讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10808936.html">Linux性能优化实战学习笔记:第六讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10809642.html">Linux性能优化实战学习笔记:第七讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10811704.html">Linux性能优化实战学习笔记:第八讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10815283.html">Linux性能优化实战学习笔记:第九讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10820252.html">Linux性能优化实战学习笔记:第十讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10592001.html">Linux性能优化实战学习笔记:第十一讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10827212.html">Linux性能优化实战学习笔记:第十二讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10833109.html">Linux性能优化实战学习笔记:第十三讲</a></p>

href="https://www.cnblogs.com/luoahong/p/10831209.html">Linux性能优化实战学习笔记:第十五讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10832062.html">Linux性能优化实战学习笔记:第十六讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10839790.html">Linux性能优化实战学习笔记:第十七讲</a><a
href="https://www.cnblogs.com/luoahong/p/10833689.html">Linux性能优化实战学习笔记:第十七讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10842424.html">Linux性能优化实战学习笔记:第十八讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10353819.html">Linux性能优化实战学习笔记:第十九讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10353904.html">Linux性能优化实战学习笔记:第二十讲</a></p>
href="https://www.cnblogs.com/luoahong/p/10844808.html">Linux性能优化实战学习笔记:第二十一讲</a></p>

 2、处理href 

sed  '/^$/d' tmpHtml.html |sed 's/href="//g'|awk -F '[">]' '{print$1}'

分解:
1、先删除空行,使用 /^$/d
2、将href=" 替换为空白
3、使用awk -F '[">]' 将此为分隔符把第一列打印出来

经过以上步骤就得到了结果
 regExp]# sed  '/^$/d' tmpHtml.html |sed 's/href="//g'|awk -F '[">]' '{print$1}'
https://www.cnblogs.com/luoahong/p/10353166.html
https://www.cnblogs.com/luoahong/p/10802102.html
https://www.cnblogs.com/luoahong/p/10808031.html
https://www.cnblogs.com/luoahong/p/10808936.html
https://www.cnblogs.com/luoahong/p/10809642.html
https://www.cnblogs.com/luoahong/p/10811704.html
https://www.cnblogs.com/luoahong/p/10815283.html
https://www.cnblogs.com/luoahong/p/10820252.html
https://www.cnblogs.com/luoahong/p/10592001.html
https://www.cnblogs.com/luoahong/p/10827212.html
https://www.cnblogs.com/luoahong/p/10833109.html
https://www.cnblogs.com/luoahong/p/10831209.html
https://www.cnblogs.com/luoahong/p/10832062.html
https://www.cnblogs.com/luoahong/p/10839790.html

6、替换匹配到的字符串

需求: 批量修改/etc/ssh/sshd_conf中的配置。

需要将这一行的注释打开并修改为no,来优化ssh的效能。

opt]# sed -ri '/^#UseDNS/cUseDNS no' sshd_config

 sed 命令解析:

-r 开启扩展正则

-i 直接修改文本

^#UseDNS 匹配#UseDNS的行,

c\ 用新文本替换定位文本,一般省略\

 opt]#  sed -ri '/^#UseDNS/c\UseDNS no' sshd_config 和

 opt]#  sed -ri '/^#UseDNS/cUseDNS no' sshd_config 等价

7、忽略大小写替换

在模式空间使用 i

8、匹配到的行整行替换

这个需求常见于修改配置。

例如

chot.qmsrpt.version=V22.0805.01

需要将=后面的内容替换为一个新的tag.

[root@meta ~]#cat /tmp/config.test
chot.qmsrpt.version = V22.0805.01
[root@meta ~]#
[root@meta ~]#
[root@meta ~]#sed -n '/^chot.qmsrpt.version/cchot.qmsrpt.version=V22.0805.02' /tmp/config.test
chot.qmsrpt.version=V22.0805.02

 

二、查找

1、查找匹配到的行

-n 参数是只打印模式匹配的行,否则会打印所有。

 参数p 代表pattern,标识匹配。

tmp]# sed -n '/target/p' ansible.cfg 
# prevents logging of tasks, but only on the targets, data is still logged on the master/controller
no_target_syslog = True
#no_target_syslog = False

如果是一个时间区间,则可以使用 " , "隔开时间区间过滤。

pg_log]# cat -n gpdb-2020-05-23_000000.csv 
     1	2020-05-23 21:56:14.524927 CST,"gpadmin","qmstst",p2588,th-625846464,"[local]",,2020-05-23 21:56:14 CST,0,,,seg-1,,,,sx1,"WARNING","01000","time constraints added on superuser role",,,,,,,0,,"auth.c",2966,
     2	2020-05-23 21:56:14.525134 CST,"gpadmin","qmstst",p2588,th-625846464,"[local]",,2020-05-23 21:56:14 CST,0,,,seg-1,,,,sx1,"FATAL","3D000","database ""qmstst"" does not exist",,,,,,,0,,"postinit.c",956,
     3	2020-05-23 21:56:22.618282 CST,"gpadmin","postgres",p2975,th-625846464,"[local]",,2020-05-23 21:56:22 CST,0,,,seg-1,,,,sx1,"WARNING","01000","time constraints added on superuser role",,,,,,,0,,"auth.c",2966,
     4	2020-05-23 21:56:22.619526 CST,"gpadmin","postgres",p2975,th-625846464,"[local]",,2020-05-23 21:56:22 CST,0,,,seg-1,,,,sx1,"FATAL","57P03","System was started in master-only utility mode - only utility mode connections are allowed",,,,,,,0,,"postinit.c",1142,

 
pg_log]# sed -n '/21:56:14.524/,/21:56:22/p' gpdb-2020-05-23_000000.csv 
2020-05-23 21:56:14.524927 CST,"gpadmin","qmstst",p2588,th-625846464,"[local]",,2020-05-23 21:56:14 CST,0,,,seg-1,,,,sx1,"WARNING","01000","time constraints added on superuser role",,,,,,,0,,"auth.c",2966,
2020-05-23 21:56:14.525134 CST,"gpadmin","qmstst",p2588,th-625846464,"[local]",,2020-05-23 21:56:14 CST,0,,,seg-1,,,,sx1,"FATAL","3D000","database ""qmstst"" does not exist",,,,,,,0,,"postinit.c",956,
2020-05-23 21:56:22.618282 CST,"gpadmin","postgres",p2975,th-625846464,"[local]",,2020-05-23 21:56:22 CST,0,,,seg-1,,,,sx1,"WARNING","01000","time constraints added on superuser role",,,,,,,0,,"auth.c",2966,
[root@gptest01 pg_log]# 

三、修改行

1、给不需要的行添加注释

对ansib 提取的结果进行处理。

&  保存查找串以便在替换串中引用 。

例如 s/my/**&**/  符号&代表查找串。my将被替换为**my**

 GP]# cat gplogpath.log |sed 's/^10/#&/'|sed 's/^find/#&/'
#10.50.10.169 | FAILED | rc=1 >>
#find: `/datap1[1-4]/gpseg*/pg_log/': No such file or directorynon-zero return code
#10.50.10.173 | SUCCESS | rc=0 >>
/datap11/gpseg8/pg_log/gpdb-2020-08-09_000000.csv
/datap12/gpseg9/pg_log/gpdb-2020-08-09_000000.csv
/datap13/gpseg10/pg_log/gpdb-2020-08-09_000000.csv
/datap14/gpseg11/pg_log/gpdb-2020-08-09_000000.csv
#10.50.10.171 | SUCCESS | rc=0 >>
/datap11/gpseg0/pg_log/gpdb-2020-08-09_000000.csv
/datap12/gpseg1/pg_log/gpdb-2020-08-09_000000.csv
/datap13/gpseg2/pg_log/gpdb-2020-08-09_000000.csv
/datap14/gpseg3/pg_log/gpdb-2020-08-09_000000.csv
#10.50.10.172 | SUCCESS | rc=0 >>
/datap11/gpseg4/pg_log/gpdb-2020-08-09_000000.csv
/datap12/gpseg5/pg_log/gpdb-2020-08-09_000000.csv
/datap13/gpseg6/pg_log/gpdb-2020-08-09_000000.csv
/datap14/gpseg7/pg_log/gpdb-2020-08-09_000000.csv
#10.50.10.174 | SUCCESS | rc=0 >>
/datap11/gpseg12/pg_log/gpdb-2020-08-09_000000.csv
/datap12/gpseg13/pg_log/gpdb-2020-08-09_000000.csv
/datap13/gpseg14/pg_log/gpdb-2020-08-09_000000.csv
/datap14/gpseg15/pg_log/gpdb-2020-08-09_000000.csv

其他注释方式 

[root@ninesun example]# sed -r 's/(.*)/#\1/' passwd # \1 位置引用
#root:x:0:0:root:/root:/bin/bash
#bin:x:1:1:bin:/bin:/sbin/nologin
#daemon:x:2:2:daemon:/sbin:/sbin/nologin
#adm:x:3:4:adm:/var/adm:/sbin/nologin
#lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
#sync:x:5:0:sync:/sbin:/bin/sync
#shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
#halt:x:7:0:halt:/sbin:/sbin/halt
#mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
#operator:x:11:0:operator:/root:/sbin/nologin
[root@ninesun example]# 
[root@ninesun example]# 

[root@ninesun example]# sed -r 's/^/#/' passwd 
#root:x:0:0:root:/root:/bin/bash
#bin:x:1:1:bin:/bin:/sbin/nologin
#daemon:x:2:2:daemon:/sbin:/sbin/nologin
#adm:x:3:4:adm:/var/adm:/sbin/nologin
#lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
#sync:x:5:0:sync:/sbin:/bin/sync
#shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
#halt:x:7:0:halt:/sbin:/sbin/halt
#mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
#operator:x:11:0:operator:/root:/sbin/nologin
[root@ninesun example]# 
[root@ninesun example]# sed -r 's/(.*)/#&/' passwd # &代表匹配到的内容
#root:x:0:0:root:/root:/bin/bash
#bin:x:1:1:bin:/bin:/sbin/nologin
#daemon:x:2:2:daemon:/sbin:/sbin/nologin
#adm:x:3:4:adm:/var/adm:/sbin/nologin
#lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
#sync:x:5:0:sync:/sbin:/bin/sync
#shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
#halt:x:7:0:halt:/sbin:/sbin/halt
#mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
#operator:x:11:0:operator:/root:/sbin/nologin
[root@ninesun example]# 
[root@ninesun example]# 
[root@ninesun example]# sed -r '1,3s/(.*)/#&/' passwd  #1,3 行注释
#root:x:0:0:root:/root:/bin/bash
#bin:x:1:1:bin:/bin:/sbin/nologin
#daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

如何避免重复注释呢? 

  • 将多个#替换成一个#

2、 删除奇数、偶数行

3、在行中任意位置添加内容

位置引用

(.)(.)(.*) 把一行的内容分隔成三部分,第一个字符 第二个字符 其他字符. 这样就可以非常灵活(注意()位置引用只能有9个)

[root@ninesun example]# sed -r 's/(.)(.)(.*)/\1\2WWW\3/' passwd 
roWWWot:x:0:0:root:/root:/bin/bash
biWWWn:x:1:1:bin:/bin:/sbin/nologin
[root@ninesun example]# 
[root@ninesun example]# sed -r 's/(.*)(.)/\1WWW\2/' passwd 
root:x:0:0:root:/root:/bin/basWWWh
bin:x:1:1:bin:/bin:/sbin/nologiWWWn

--update 2022年6月23日14:56:52

sed -ri 's/.*swap.*/#&/' /etc/fstab
只有一个()的时候,后面引用它时可以直接用  & 

sed -i '/swap/s/^/#/' fstab  # 匹配查找替换也是可以的

批量重命名文件

 对于批量重命名文件可以使用xargs -I 也可以使用sed。相对来说sed更灵活,批量重命名是可逆的.

sed]# ls | grep test | xargs -I GG echo "mv GG ./backup/GG.back"
mv test10.sql ./backup/test10.sql.back
mv test1.sql ./backup/test1.sql.back
mv test2.sql ./backup/test2.sql.back
mv test3.sql ./backup/test3.sql.back
mv test4.sql ./backup/test4.sql.back
mv test5.sql ./backup/test5.sql.back
mv test6.sql ./backup/test6.sql.back
mv test7.sql ./backup/test7.sql.back
mv test8.sql ./backup/test8.sql.back
mv test9.sql ./backup/test9.sql.back
mv test.sql ./backup/test.sql.back


sed]# ls | grep test | sed -r 's/(.*)/mv \1 \1.back/g'
mv test10.sql test10.sql.back
mv test1.sql test1.sql.back
mv test2.sql test2.sql.back
mv test3.sql test3.sql.back
mv test4.sql test4.sql.back
mv test5.sql test5.sql.back
mv test6.sql test6.sql.back
mv test7.sql test7.sql.back
mv test8.sql test8.sql.back
mv test9.sql test9.sql.back
mv test.sql test.sql.back
[root@ninesun sed]# ls | grep test | sed -r 's/(.*)/mv \1 \1.back/g'|bash
[root@ninesun sed]# ls -l
total 48
drwxr-xr-x 2 root root 4096 Jan 13 16:26 backup
-rw-r--r-- 1 root root   61 Jan 11 11:53 test10.sql.back
-rw-r--r-- 1 root root   60 Jan 11 11:53 test1.sql.back
-rw-r--r-- 1 root root   60 Jan 11 11:53 test2.sql.back
-rw-r--r-- 1 root root   60 Jan 11 11:53 test3.sql.back
-rw-r--r-- 1 root root   60 Jan 11 11:53 test4.sql.back
-rw-r--r-- 1 root root   60 Jan 11 11:53 test5.sql.back
-rw-r--r-- 1 root root   60 Jan 11 11:53 test6.sql.back
-rw-r--r-- 1 root root   60 Jan 11 11:53 test7.sql.back
-rw-r--r-- 1 root root   60 Jan 11 11:53 test8.sql.back
-rw-r--r-- 1 root root   60 Jan 11 11:53 test9.sql.back
-rw-r--r-- 1 root root   52 Jan 11 11:34 test.sql.back

 4、sed -r 读取外部文件

要区分 2r和/2/r ,第一个是第二行,第二个是正则匹配2的行

 5、匹配到的行写入其他文件 

3,$w 第三行到最后一行写入new1.txt

最佳多行 

 6、模式空间中的a i c

  • a 行后追加
  • i 行前追加
  • c 替换行

 7、-n 隔山打牛

有时候匹配的时候,不太好这,比如找个地方不好找,但是旁边有高楼,那就先找到高楼,再去找旁边要找的地方。

 -n可以使用多次

多行命令

sed 命令的基础功能时, sed 命令都只是针对单行数据执行操作,但是,有时我们需要对多行的数据执行特定操作。如在文本中查找一串字符串"xxxxxxxxxxxx",它很有可能出现在两行中,每行各包含其中一部分。

[root@ninesun example]# cat sed_test.txt 
Make sure that the heap size is
set to about half the memory available
on the system and that the owner
of the process is allowed to use this
limit
[root@ninesun example]# 
[root@ninesun example]# sed '/lable/{N;s/\n/ /}' sed_test.txt 
Make sure that the heap size is
set to about half the memory available on the system and that the owner
of the process is allowed to use this
limit

-N 将数据流中的两个文本行合并到同一个模式空间中。文本行仍然用换行符分隔

[root@ninesun example]# cat data4.txt 
On Tuesday, the Linux System
Administrator's group meeting will be held.
All System Administrators should attend.


[root@ninesun example]# sed '
> s/System Administrator/Desktop User/
> N
> s/System\nAdministrator/Desktop\nUser/
> ' data4.txt
On Tuesday, the Linux Desktop
User's group meeting will be held.
All Desktop Users should attend.

 8、sed -h -H 和-g -G 写入

sed是一行一行处理文本的,将每一行写入模式空间进行处理。

如果使用了 -h -H 和-g -G则代表使用暂存空间(保持空间)和模式空间进行交互。

当启动sed编辑器时,暂存空间(保持空间)只有一个空行。 不是处理每行都有空行。

需求1: 第一行复制到最后一行

需求2: 第一行移动到最后一行

1{h;d};$G : 从模式空间取第一行覆盖写入暂存空间,然后模式空间中d删除。$G代表处理模式空间最后一行的时候从暂存空间取出第一行追加写入模式空间

 如果是$g 可以看到最后一行被覆盖掉了。

需求3: 使用第一行覆盖所有内容

'1h;2,$G' :

第一行从模式空间存入暂存空间, 模式空间输出第一行内容

模式空间中处理第二行到最后一行时,g从暂存空间取出第一行覆盖写入2,$的模式空间(是一个动态的过程一行一行处理)

如果是G就是追加写,没写入模式空间一行,就从暂存空间取回来root那一行。

需求4: 加倍行间距

sed 'G' data2.txt  

sed '$!G' data2.txt  去掉最后一行后的空行

sed '/^$/d ; $!G' test.log 如果文本中含有空行

9、sed对广义空行的处理

对空行的定义是处理该问题的关键.

  • ^$ 整个空行
  • \t table键空行
  • space 空行

文件内容如下:

vim下 set list可现实特殊字符

现在 TAB 键显示为 ^I,而 $显示在每行的结尾,以便你能找到可能会被你忽略的空白字符在哪里。 

 如何打开文件中的注释行呢?

 ^[ \t]*#  :以空格或table开始到#号(包括#号)出现一次或多次 

example]# sed -r '/^[ \t]*#/d' space.txt 
asdasd
/etc/hosts


sdsdwqeqw

 如何删除注释时同时删除空行?

example]# sed -r '/^[ \t]*#/d; /^$/d' space.txt

example]# sed -r '/^[ \t]*($|#)/d' space.txt # 更简便

 

10、sed修改ssh配置

掌握a\: 追加, c\ :匹配到的内容进行替换 <其中\可省略>,详情可参考1.6

11、sed使用外部变量

 12、sed实现字符串倒转

1.最简单的实现方式应该是tac。

 2.使用暂存空间和模式空间实现

按照如下几个步骤实现倒转: 

(1) 在模式空间中放置一行;
(2) 将模式空间中的行放到保持空间中;
(3) 在模式空间中放入下一行;
(4) 将保持空间附加到模式空间后;
(5) 将模式空间中的所有内容都放到保持空间中;
(6)重复执行第(3)~(5)步,直到所有行都反序放到了保持空间中;
(7) 提取并打印行。

example]# sed -r '1!G; $!h; $!d' reverse.txt

如果不使用-r

-n 在处理时不打印行

 sed -n '{1!G ; h ; $p }' reverse.txt

 

--update 2022年3月5日14:19:47

这个过程确实不是很好想,可以使用sedsed来debug这个命令。

例如

compare the normal sed run and the sedsed debug run for a script to reverse the line order (similar to Unix tac):

$ echo -e 'A\nB\nC' | sed '1!G;h;$!d'
C
B
A
$ echo -e 'A\nB\nC' | sedsed --debug '1!G;h;$!d'
PATT:A$
HOLD:$
COMM:1 !G
PATT:A$
HOLD:$
COMM:h
PATT:A$
HOLD:A$
COMM:$ !d
PATT:B$
HOLD:A$
COMM:1 !G
PATT:B\nA$
HOLD:A$
COMM:h
PATT:B\nA$
HOLD:B\nA$
COMM:$ !d
PATT:C$
HOLD:B\nA$
COMM:1 !G
PATT:C\nB\nA$
HOLD:B\nA$
COMM:h
PATT:C\nB\nA$
HOLD:C\nB\nA$
COMM:$ !d
PATT:C\nB\nA$
HOLD:C\nB\nA$
C
B
A

三、统计

3.1 怎么检查一个文本文件中某一行的长度?

这里n表示行号,p打印出匹配内容(到标准输出),该命令通常与-n命令行选项连用。那么,怎样来获取长度计数呢?很明显,我们需要通过管道输出给wc命令来计算。

# sed –n 'n p' file.txt | wc –c

要得到文本文件第五行的长度,运行如下命令:

 data]# sed -n '5 p' hmslogAD.txt |wc -c
67

四、修改文本

4.1 如何向文本指定位置插入另外一个文本?

 有这么一个需求,需要往指定的html中插入新生成的table标签,前面的样式是固定的。GP 以html格式生成的查询结果滤出关键字table然后插入第37行之后,最后邮件发送出来。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <h1 align="center"> GP 慢查询</h1>
  6. </head>
  7. <body>
  8. <!-- CSS goes in the document HEAD or added to your external stylesheet -->
  9. <style type="text/css">
  10. table.imagetable {
  11.     font-family: verdana,arial,sans-serif;
  12.     font-size:11px;
  13.     color:#333333;
  14.     border-width: 1px;
  15.     border-color: #999999;
  16.     border-collapse: collapse;
  17. }
  18. table.imagetable th {
  19.     background:#b5cfd2 url('cell-blue.jpg');
  20.     border-width: 1px;
  21.     padding: 8px;
  22.     border-style: solid;
  23.     border-color: #999999;
  24. }
  25. table.imagetable td {
  26.     background:#dcddc0 url('cell-grey.jpg');
  27.     border-width: 1px;
  28.     padding: 8px;
  29.     border-style: solid;
  30.     border-color: #999999;
  31. }
  32. </style>
  33. <!-- Table goes in the document BODY -->
  34. <table class="imagetable">
  35. <tr>
  36.     <th>rank</th><th>content</th>
  37. </tr>
  38. 这里填上需要的table数据
  39. </table>
  40. </body>
  41. </html>

这里主要讨论和sed有关的地方,sed -i 可以对文件直接进行操作。

一般使用最多的是sed -i进行 替换。

使用sed 添加一个文件到指定文件指定行。

  • 37行
  • tmp.txt 需要添加在37行之后的文件
  • slowQuery.html 目标文件,对应上面的html文件
sed -i "37 r /home/scripts/slowQuery/tmp.txt" slowQuery.html

结果:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <h1 align="center"> GP 慢查询</h1>
</head>
<body>
<!-- CSS goes in the document HEAD or added to your external stylesheet -->
<style type="text/css">
table.imagetable {
    font-family: verdana,arial,sans-serif;
    font-size:11px;
    color:#333333;
    border-width: 1px;
    border-color: #999999;
    border-collapse: collapse;
}
table.imagetable th {
    background:#b5cfd2 url('cell-blue.jpg');
    border-width: 1px;
    padding: 8px;
    border-style: solid;
    border-color: #999999;
}
table.imagetable td {
    background:#dcddc0 url('cell-grey.jpg');
    border-width: 1px;
    padding: 8px;
    border-style: solid;
    border-color: #999999;
}
</style>

<!-- Table goes in the document BODY -->
<table class="imagetable">
<tr>
    <th>rank</th><th>content</th>
</tr>
<tr valign="top">
    <td align="right">1</td>
    <td align="left">查询提交时间 :2020-10-15 15:42:35.24;当前gp有慢查询:procpid :6829;sess_id :7051266;sql为 :select glass_id, min(substring(glass_id,2,2)) as year, min(substring(glass_id,4,1)) as month  from wpp_fdefect_panel_f where db_timestamp &gt;= '2020-10-15 15:10:00.0' and db_timestamp &lt; '2020-10-15 15:30:00.0' and ope_id = 'CB353' and real_flg = 'Y' and substring(glass_id,1,1) in ('A','C') and glass_id not like '%*%' group by glass_id  order by year, month</td>
  </tr>
  
</table>
</body>
</html> 





五、统计某行中包含数字的个数

使用wc + sed + 正则实现

]#echo "w9q9e3 12312312"|wc -m
16

]#echo "w9q9e3 12312312"|wc -L
15

]#echo "w9q9e3 12312312"|wc -c
16

#wc -L选项,统计最长行的长度
         -L, --max-line-length
              print the length of the longest line
         -l, --lines
              print the newline counts
   -l用于统计有多少个新行 -L 代表的是某行中最长的长度
   	    -c, --bytes
              print the byte counts

       -m, --chars
              print the character counts

借助sed 和正则

正则 [^0-9] 代表非数字

模式s  使用替换模式替换

模式g  将模式2粘贴到/pattern n/

]#echo "w9q9e3 12312312"|sed  s'/[^0-9]//'g
99312312312

将非数字替换为空白就得到了如上数字串. 

此处要使用wc的-L 参数,  wc的参数如上. 

]#echo "w9q9e3 12312312"|sed  s'/[^0-9]//'g|wc -L
11

六、sed 和正则搭配使用

分离数组和字母

输入:

tmp]# cat sed.txt
abc1234567890
abc0987654321
xyz1234567890
输出:

1234567890
0987654321
1234567890

方法一

 tmp]# sed -n 's/^\([a-z]\{3\}\)\([0-9]\{3,\}\)/\2/p' sed.txt
1234567890
0987654321
1234567890
  • ([a-z]{3})  字母匹配三次
  • ([0-9]{3,}) 数字匹配至少三次,最多不限

以上两个正则将文本分为两部分,\2p 打印第二部分匹配到的内容就是我们想要的.

反斜线符号“ \ ”在Bash中被解释为转义字符,用于去除一个单个字符的特殊意义,它保留了跟随在之后的字符的字面值,除了换行符

如果要输出字母:取正则的第二个分组,即\2

]# sed -n 's/^\([a-z]\{3\}\)\([0-9]\{3,\}\)/\1/p' sed.txt
abc
abc
xyz


方法二:引入正则

]# sed -r -n 's/^([a-z]{3})([0-9]{3,})/\2/p' sed.txt
1234567890
0987654321
1234567890


这里有个小坑,就是转义, 如果在括号前加\ 则代表原义括号了。

总之一句话,想少用\  那你就用-r

格式化数字串

输入:1234567

输出:123,456,7 或者1,234,567

[root@ninesun example]# echo "1234567" | sed -r 's/([0-9]{3})([0-9]{3})(.*)/\1,\2,\3/'
123,456,7
[root@ninesun example]# 
[root@ninesun example]# echo "1234567" | sed -r 's/(.*)([0-9]{3})([0-9]{3})/\1,\2,\3/'
1,234,567

如果输入的字符串越来越长如何解决?位置引用最多只能用9个括号.

例如123456792378937892498279842,如何分隔?

需要引入分支,使用子模式在大数字中插入逗号

设置一个分支标签LABEL供"b"、"t"命令跳转

'b LABEL'
无条件跳转到标签LABEL上。如果LABEL参数省略,则跳转到SCRIPT的尾部准备进入下一个sed循环,即跳转到隐含动作auto_print的前面。

't LABEL'
如果对最近读入的行有"s"命令的替换成功了,则跳转到LABEL标签处。如果LABEL参数省略,则跳转到SCRIPT的尾部准备进入下一个sed循环,即跳转到隐含动作auto_print的前面。

有以上前置知识后看下面这个例子就好理解了。

[root@ninesun ~]# echo "This, is, a, test, to, remove, commas." | sed -n '{:l; s/,//1p; tl}'
This is, a, test, to, remove, commas.
This is a, test, to, remove, commas.
This is a test, to, remove, commas.
This is a test to, remove, commas.
This is a test to remove, commas.
This is a test to remove commas.
[root@ninesun ~]# 
[root@ninesun ~]# 
[root@ninesun ~]# echo "This, is, a, test, to, remove, commas." | sed -n '{:l; s/,//1p; bl}'
This is, a, test, to, remove, commas.
This is a, test, to, remove, commas.
This is a test, to, remove, commas.
This is a test to, remove, commas.
This is a test to remove, commas.
This is a test to remove commas.
  •  :l 定义一个l标签
  • s/,/ /1p 从左往右第一个逗号出现的位置换位空格
  • tl 最后一次替换成功,标签结束(t和l之间的空格可省略)

分支的思想类似于迭代.

大数字中插入逗号 

#方式一: 分多行书写
]# echo "123456792378937892498279842" | sed '{
:start
s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/
t start
}'
123,456,792,378,937,892,498,279,842

#方式二:写在一行
~]# echo "12345672332135490854389679123" | sed -r '{:start; s/(.*[0-9])([0-9]{3})/\1,\2/; t start}'
12,345,672,332,135,490,854,389,679,123
  • .*[0-9]
  • [0-9]{3}

这个模式会查找两个子模式。第一个子模式是以数字结尾的任意长度的字符。第二个子模式
是若干组三位数字。如果这个模式在文本中找到了(对应分支lable 中的t),替代文本会在两个子模式之间加一个逗号,每个子模式都会通过其位置来标示。这个脚本使用测试命令来遍历这个数字,直到放置好所有的逗号。 

打印序号

[root@ninesun example]# sed '=' passwd
1
root:x:0:0:root:/root:/bin/bash
2
bin:x:1:1:bin:/bin:/sbin/nologin
3
daemon:x:2:2:daemon:/sbin:/sbin/nologin
4
adm:x:3:4:adm:/var/adm:/sbin/nologin
5
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6
sync:x:5:0:sync:/sbin:/bin/sync
7
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8
halt:x:7:0:halt:/sbin:/sbin/halt
9
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10
operator:x:11:0:operator:/root:/sbin/nologin
# N将匹配到的行与下一行合并
[root@ninesun example]# sed '=' passwd | sed -r 'N;s/\n/ /g'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 operator:x:11:0:operator:/root:/sbin/nologin



[root@ninesun example]# 
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 operator:x:11:0:operator:/root:/sbin/nologin

打印末尾行

sed采用行号计数器即时计数,每读取一行,计数器就加1。因此sed在读取到最后一行前,不知道后面还有多少行,也不知道什么时候才是最后一行。直到读取到输入流的最后一行,sed为该行打上"$"标记,表示这是最后一行。"$"只是一个标记符号,并非行号,行号只在计数器中记录,因此无法通过"$"来计算出倒数几行,例如"$-1"是错误的写法。

例如,要输出倒数10行,这个窗口就一直维持在10行的固定大小。当读取到最后一行时,可以通过"$"符号来判断这是否是最后一行,是的话就输出该窗口,否则不输出该窗口的数据。类似于一个滑动窗口。

chapter21]# sed ':l $q; N; 11,$D; b l' data7.txt

去掉字符串中的引号

 ⚡ root@ninesun ~  echo ""tag_name": "v1.3.1"," | sed -E 's/.*"v([^"]+)".*/\1/'
tag_name: v1.3.1,

替换模式将括号中的引用(非引号出现 1次或多次)替换掉

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MyySophia

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值