目录

一、替换

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  dsd2    /etc/hosts3
[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

总结:

  • awk '{print strftime("%Y-%m-%d %H:%M:%S"),$0}'    为当前行最前面添加时间。
  • 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:03opt]# 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.backsed]# 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/hostssdsdwqeqw

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

example]# sed -r '/^[ \t]*#/d; /^$/d' space.txtexample]# 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-lengthprint the length of the longest line-l, --linesprint the newline counts-l用于统计有多少个新行 -L 代表的是某行中最长的长度-c, --bytesprint the byte counts-m, --charsprint 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次或多次)替换掉

Linux sed实战相关推荐

  1. Linux sed实战(MarkDown版本)

    文章目录 一.替换 1.全局替换shell中的某个字符. 2.正则匹配空行并删除 3.替换经典案例(正则) 4.时间处理 5.滤出html中href 元素后的网址 6.替换匹配到的字符串 7.忽略大小 ...

  2. linux sed 批量替换多个文件中的字符串

    原文: http://blog.csdn.net/kauu/article/details/1757325 一.linux sed 批量替换多个文件中的字符串 sed -i "s/oldst ...

  3. linux sed 选取,linux sed 替换(整行替换,部分替换)、删除delete、新增add、选取...

    sed命令行格式为: sed [-nefri] 'command' 输入文本 常用选项: -n∶使用安静(silent)模式.在一般 sed 的用法中,所有来自 STDIN的资料一般都会被列出到萤幕上 ...

  4. linux a文本编辑大全,Linux sed 命令 - Linux文档编辑命令大全

    Linux sed 命令是利用脚本来处理文本文件. sed 可依照脚本的指令来处理.编辑文本文件. Sed 主要用来自动编辑一个或多个文件.简化对文件的反复操作.编写转换程序等. 语法sed [-hn ...

  5. Linux脚本实战之猜数字

    Linux脚本实战之猜数字 一.脚本要求 二.脚本示例一 三.脚本示例二 一.脚本要求 1.系统环境为RHEL8.0 2.脚本生成一个100以内的随机数,提示用户猜数字. 3.根据用户的输入,提示猜对 ...

  6. Linux脚本实战之检测网卡流量

    Linux脚本实战之检测网卡流量 一.脚本要求 二.脚本内容 三.运行脚本 一.脚本要求 1.检测网卡流量,并按规定格式记录在日志中,输出到/data/net.log/目录中以执行脚本时间命令的文件中 ...

  7. learn Linux sed command

    learn Linux sed command一.参考文档:1. sed命令详解http://qifuguang.me/2015/09/21/sed%E5%91%BD%E4%BB%A4%E8%AF%A ...

  8. 打开高效文本编辑之门_熟悉Linux Sed的替换命令

    Linux sed S替换命令常见使用案例 声明与简介 sed:Stream Editor文本流编辑,sed是一个"非交互式的"面向字符流的编辑器.本文主要以实际的数据来介绍sed ...

  9. Linux sed 写命令常见使用案例

    Linux sed w命令常见使用场景汇总 声明与简介 sed:Stream Editor文本流编辑,sed是一个"非交互式的"面向字符流的编辑器.本文主要以实际的数据来介绍sed ...

最新文章

  1. mysql中文无法显示
  2. 「吐血」我把 10 年的全部学习资源都分享在这里了
  3. PHP写猜数字,PHP算法之猜数字
  4. 代码不是重点, 领悟OO思想(一)
  5. Android Retrofit下载文件进度
  6. 漫画:图的最短路径问题
  7. 演练Ext JS 4.2自定义主题
  8. java多个文件加密压缩_Java实现自动压缩文件并加密的方法示例
  9. iOS7—Day by day—Day16:Decoding QR Codes With AVFoundation
  10. 论文数据统计Task1
  11. 美妆短视频的定位分享,教程、技巧都可做,还可尝试变装内容
  12. acc之ADTS解说一
  13. ssh连接服务器 一段时间不动后 无响应
  14. 如何检查DirectX的版本(用于Windows Phone Developer Tools的安装检查)
  15. 基于RFID定位技术的工地人员定位考勤系统-工地人员定位-新导智能
  16. 2022-2028年全球管道监测系统收入年复合增长率CAGR为 3.8%
  17. 制作自己的docker镜像
  18. 蜻蜓FM实时推荐系统的发展和演进
  19. Keil MDK编译出现..\USER\stm32f10x.h(428): error: #67: expected a “}“错误的解决办法
  20. 小米盒子进入android,当北市场教您如何使用小米盒子安装非Android大型游戏

热门文章

  1. TabLayout简单例子
  2. pandas多场景业务实战-指标计算
  3. 2019计算机电源海关征税,2019年海关税率汇总,海淘常见产品轻松算税费啦~
  4. 空域图像增强-图像灰度变换
  5. 【微信公众号H5授权登录】
  6. Python-pydicom读取dcm文件报错-2021.6.5
  7. 图像特征之SURF特征匹配
  8. 两个div并排 左边div宽固定 右边自适应
  9. PWM控制电机转速的原理
  10. 转有关IC卡与ID卡的重大区别