sed正则表达式的使用以及使用sed修改配置文件的典型案例
Posted bluishglc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sed正则表达式的使用以及使用sed修改配置文件的典型案例相关的知识,希望对你有一定的参考价值。
场景一
场景描述:找到指定的行,将其注释掉(是直接注释,不是修改值),然后紧接下一行插入新内容
这种场景在修改配置文件时最常见,注释和插入的往往是同一配置项,为了维护配置文件的可读性,通常会将关系紧密的几项配置放在一起,这就是为什么需要紧接下一行插入新内容的原因。
编辑示例:
我们现在要编辑/var/kerberos/krb5kdc/kdc.conf文件,编辑内容为:找到现有的database_name配置项将其注释掉,然后紧邻下一行插入新的配置项(因为两项配置关系密切)。
...
#database_name = /var/kerberos/krb5kdc/principal
database_module = openldap_ldapconf
...
编辑命令:
# 找到database_name这一行,将其注释掉;
# 并在下一行插入:database_module = openldap_ldapconf
sed -i 's/\\(^\\s*\\)database_name\\(.*\\)/\\1#database_name\\2\\n\\1database_module = openldap_ldapconf/g' /var/kerberos/krb5kdc/kdc.conf
知识点:
这条sed语句有很多值得学习和复用的地方,总结如下:
-
^\\s*
:考虑可能的缩进,增强匹配的适用性 -
\\(
,\\)
,\\\\\\|
,\\1
,\\2
:注意要转义的字符 -
\\1
,\\2
:注意对分组的运用,分组的用处在于能将匹配到的内容作为一个整体“复制”到期望的位置。本例中如果只是想在database_name前加上一个#符号,是用不到分组的,这里用到分组的原因是:替换的字符串要在原字符串的基础上append新内容,这就需要将原字符串中的“缩进部分”和“database_name的后半部分”复制到替换字符串中,因此需要对这两个独立的部分进行“标记”,以便在替换字符串中“引用” -
\\n
:新起一行插入内容
关于grep正则表达式有哪些字符需要转义,可参考:
https://www.gnu.org/software/findutils/manual/html_node/find_html/grep-regular-expression-syntax.html
场景二
场景描述:文件中可能有针对某一项配置的多行记录,有的是生效中的配置,有的是被注释掉的候选配置,需求是找到这些冗余的项,全部移除,然后在原第一行中插入唯一生效的项。
场景二和场景一是有区别的:场景一要注释掉的是一个确定存在且生效中的项,不存在多个注释或未注释的同名项,新插入的项也与注释掉的项不同(仅仅是关系紧密); 场景二的处理的则是可能存在多个注释或未注释的同名项,且新插入的项还是同一项,这样在判断哪些项需要注释,哪些项需要取消取消注释就会非常麻烦,所以方案二的处理策略是:全部移除,以新插入的项为准。这样会带来一个问题,一旦移除这些已有的项,就找不到合适的位置来插入新项了,所以,移除前,需要先把行号记录下来,然后在原第一行处插入,这样,可以保持配置项的上下关联性。
编辑示例:
我们现在要编辑/etc/ssh/sshd_config文件,其内容可能如下,也可能是其他状况,总之会存在多项UsePAM和PasswordAuthentication的行,有的是注释掉的,有的是生效中的:
...
UsePAM no
#UsePAM yes
...
PasswordAuthentication no
#PasswordAuthentication yes
...
我们希望编辑后是这个样子:
...
UsePAM yes
...
PasswordAuthentication yes
...
编辑命令:
items=(UsePAM PasswordAuthentication)
for item in $items[@]; do
searchExp="^\\s*[#]\\?\\s*$item\\s*\\(yes\\|no\\)$"
# 所有待删除的行号
lineNums=($(grep -n -e "$searchExp" /etc/ssh/sshd_config | cut -d: -f1))
# 生成sed行表达式
printf -v linesExp "%sd;" "$lineNums[@]"
# 删除所有行
sed -i -e "$linesExp" /etc/ssh/sshd_config
# 在原第一行处插入新配置(为了保持配置项出现在合适的位置)
sed "$lineNums[0]i $item yes" -i /etc/ssh/sshd_config
done
知识点:
-
grep -n -e '^\\s*[#]\\?\\s*PasswordAuthentication\\s*\\(yes\\|no\\)$' /etc/ssh/sshd_config | cut -d: -f1
:查找指定内容在文件中的行号 -
sed -i -e '61d;63d;' /etc/ssh/sshd_config
:删除61和63行 -
sed '61i PasswordAuthentication yes' -i /etc/ssh/sshd_config
:在第61行前(i:是insert,行前插入,a:是append,行后插入)插入“PasswordAuthentication yes”
以上是关于sed正则表达式的使用以及使用sed修改配置文件的典型案例的主要内容,如果未能解决你的问题,请参考以下文章