sed 三个不同场景的插入方式

 

2020-06-21

好久没写周分享了。

指定行后插入文本

最简单的插入方式,比较适合对要修改的文件有比较明确了解的情况。

Terminal window
1
sed -i '17a\Port 1234' /etc/ssh/sshd_config

执行后将会在 SSH 的配置文件的第 17 行插入 Port 1234

涉及选项和参数

  • -i:将会直接对文件进行修改;
  • 17a:在第指定行行后插入数据,这里是第 17 行;

修改匹配行文本

虽然在指定行后添加直截了当,但适应性不是不强,如果已存在有效的端口配置,此时新增一行端口可能会造成冲突,所以应对更复杂情况下需要另一个方法:

Terminal window
1
sed -ir '/Port /{s/#//;s/[0-9].+/12345/}' /etc/ssh/sshd_config

相较于前一个方法,这个命令仅会在原有的端口配置上修改,当端口配置未注释时,移除#,并将之后的数字替换成12345

涉及选项和参数

  • -r:使用正则表达式
  • s/:替换指定字符
  • [0-9].+:匹配重复出现一次及以上的数字;

判断文本存在

有时会遇到在某些情况下,需要判定某个条件是否匹配从而执行不同操作,比如说在确定默认端口未修改的情况下指定一个新端口,但又不想直接修改原配置:

Terminal window
1
sed -i '/#Port 22/a\Port 12345' /etc/ssh/sshd_config

命令将会匹配#Port 22,并在匹配行下一行新增Port 12345

上面是数据匹配的情况,而想要在不匹配时执行则较为麻烦一些,虽然不是很适合,还是以 SSH 端口为例:

Terminal window
1
sed -i 's/Port/&/; t; 17a Port 12345' /etc/ssh/sshd_config

执行后只会在未匹配到Port的情况下在第 17 行增加Port 12345,当然这里也可以使用1a表示首行,或者使用$a表示尾行。反之则不进行插入操作。

涉及选项和参数

  • &:表示已匹配的源数据;
  • t:if 分支;

注:

最后一个命令有个小 BUG,之前主要用于修改 hosts 文件,使用正常;但在写文章测试时发现如果要操作的文件操作 102 行将会导致判断失效。也就是无论是否匹配都会插入数据,目前原因未知。

此外,虽然命令在不匹配时不会执行后续操作,但第一个替换操作仍旧会执行,目前暂用&绕过,不过应该还可以做进一步的改善。

参考