如何使用任何流编辑器(如 sed 或 awk)将条目附加到多行条目的末尾

How to append entry the end of a multi-line entry using any of stream editors like sed or awk

我正在尝试使用脚本将主机名附加到 sudoers 文件中特定 Host_Alias 字段的多行条目的末尾。

当前的 sudoers 文件有一个条目类似于:

Host_Alias  srv_linuxestate= \
            host10,host12,host13,host1,host50,\
            host16,host1,host2,host11,host15,host21,\
            host3,host14

我需要的输出类似于下面我添加的 ",host25"

Host_Alias  srv_linuxestate= \
            host10,host12,host13,host1,host50,\
            host16,host1,host2,host11,host15,host21,\
            host3,host14,host25

这段前后还有更多行。

hosts 的值可能会更改而不是固定的。还可能有更多行,如上所示,这些行在不完整行的末尾使用“\”分隔。

任何 help/pointers 都很好。

使用带空记录分隔符的 awk:

awk -v RS= '=="Host_Alias" {[=10=] = [=10=] ",host25"} 1' /etc/sudoers
Host_Alias  srv_linuxestate= \
            host10,host12,host13,host1,host50,\
            host16,host1,host2,host11,host15,host21,\
            host3,host14,host25

这是假设在 Host_Alias 的最后一行之后有一个空行,就像在常规 sudoers 文件中一样。

这是一个 sed 版本:

/^Host_Alias/{                  # whenever we match Host_Alias at line start
:
/\$/{N;b}                      # if backslash, append next line and repeat
s/$/,host25/                    # add the new host to end of line
}

如果您需要将新主机添加到其中一个主机别名,请调整第一个匹配项以适应。在您的示例中,它可能应该是 /^Host_Alias *srv_linuxestate=/,或者如果可能有制表符而不是空格,则应该是 /^Host_Alias[ \t][ \t]*srv_linuxestate=/

如果你需要它作为单行,那就变成 sed -i -e '/^Host_Alias[ \t][ \t]*srv_linuxestate=/{;:;/\$/{N;b};s/$/,host25/;}' /etc/sudoers

sed 用于单行上的简单替换,仅此而已。在 20 世纪 70 年代中期发明 awk 时,所有用于执行任何其他操作的神秘 sed 结构都已过时,因此只需使用 awk:

$ awk '/Host_Alias/{f=1} f && !/\/{[=10=]=[=10=]",host25"; f=0} {print}' file
Host_Alias  srv_linuxestate= \
            host10,host12,host13,host1,host50,\
            host16,host1,host2,host11,host15,host21,\
            host3,host14,host25

上面只是在找到包含 Host_Alias 的行时设置一个标志,当设置该标志并且当前行不包含 \ 时,它会将 ,host25 添加到行尾并清除标志。

简单、清晰、可维护、高效、可移植、可扩展等等 - 在各个方面都比等效的 sed 解决方案更好。