sed / awk在2个匹配项之间插入行,但仅在没有其他模式的情况下

时间:2017-03-24 11:01:56

标签: bash awk sed

为了编写自动安装和配置Fail2Ban的脚本,我需要一种方法来修改/etc/fail2ban/jail.local。我的问题是,我需要在文件的特定部分添加一行,但前提是该区域中不存在模式enabled = true。还有其他领域不应该写enable = true

以下seds工作正常,但不检查是否已有enabled = true

sed '/\[apache-auth\]/{x;s/.*/./;x};/port/{x;/^.$/{x;s/^/enabled = true\n/;x};s/^/./;x}' -i /etc/fail2ban/jail.local 
sed '/\[apache-badbots\]/{x;s/.*/./;x};/port/{x;/^.$/{x;s/^/enabled = true\n/;x};s/^/./;x}' -i /etc/fail2ban/jail.local
sed '/\[apache-noscript\]/{x;s/.*/./;x};/port/{x;/^.$/{x;s/^/enabled = true\n/;x};s/^/./;x}' -i /etc/fail2ban/jail.local
sed '/^\[sshd\]/{x;s/.*/./;x};/port/{x;/^.$/{x;s/^/enabled = true\n/;x};s/^/./;x}' -i /etc/fail2ban/jail.local

更新添加所需信息

原始文件

[sshd]

port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

[apache-auth]

port     = http,https
logpath  = %(apache_error_log)s


[apache-badbots]
# Ban hosts which agent identifies spammer robots crawling the web
# for email addresses. The mail outputs are buffered.
port     = http,https
logpath  = %(apache_access_log)s
bantime  = 172800
maxretry = 1


[apache-noscript]

port     = http,https
logpath  = %(apache_error_log)s

预期输出

[sshd]

enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
#
# HTTP servers
#

[apache-auth]

enabled = true
port     = http,https
logpath  = %(apache_error_log)s


[apache-badbots]
# Ban hosts which agent identifies spammer robots crawling the web
# for email addresses. The mail outputs are buffered.
enabled = true
port     = http,https
logpath  = %(apache_access_log)s
bantime  = 172800
maxretry = 1


[apache-noscript]

enabled = true
port     = http,https
logpath  = %(apache_error_log)s

英语不是我的母语,所以请不要判断我的拼写错误。我也不确定,如果这是本课题的正确网站。

2 个答案:

答案 0 :(得分:2)

这可能适合你(GNU sed):

sed -nr '/^\[(apache-(auth|loadbots|noscript)|sshd)\]/{:a;x;/./!bb;/enabled = true/!s/^\w/enabled = true\n&/M;p;:b;x;h;d};H;$ba;d' file

这将该部分存储在保留空间中,如果它尚不存在则插入enabled = true并打印出该部分。

详细说明:

command line switches -r-n已激活,这样可以更容易地为前一个和可选的打印表达正则表达式(grep-like,即命令p或对于后者,P必须存在。

该命令由if-then-else。

组成

如果当前行以[开头并且包含四个单词之一,然后是],则{}之间的命令将被执行。

打开{后的第一个命令是占位符,在满足文件结束条件时使用。

x表示使用保留空间(HS)切换模式空间(PS)。 Sed有two registers,PS是当前行(减去换行符)读入的地方。 HS是一个备用寄存器,由程序员自行决定使用。

下一个命令/./!bb检查HS是否为空(如果这是第一次执行此代码,那将是这样),如果是,则跳转到:b名称空间,输出以下代码。

现在已知HS包含一行或多行,检查这些行是否包含字符串enabled = true,如果不包含,则在第一行的前面插入字符串enabled = true以单词字符开头。

无论匹配或不匹配,HS都会使用p命令打印。

分支名称空间现在被加载:b并且HS和PS被交换,当前行替换HS h中的任何内容然后删除d,这结束了处理那条线。

如果第一个正则表达式失败:当前行被附加到HS H并被删除d,除非它是最后一行,在这种情况下处理被定向到名称空间{{1}通过命令:a。这涵盖了文件结束条件,其中HS中的行将需要如上所述进行处理。

答案 1 :(得分:0)

awk救援!

awk -v sections='sshd apache-auth apache-badbots apache-noscript' -v RS= -v ORS="\n\n" '
     BEGIN     {n=split(sections,a); 
                for(i=1; i<=n; i++) sec["["a[i]"]"]} 
     $1 in sec {$2 = "\nenabled = true\n"}1' file

维护sections变量中的标记,并为相应的部分插入所需的行。期望节标题是该行的唯一条目。