regex - Perl/Sed 命令多次替换相同的模式

标签 regex perl awk sed ubuntu-16.04

我需要使用 perl 或 sed 等命令在 /etc/xinetd.d/chargen 中设置 disable=no

/etc/xinetd.d/chargen内容为:

# description: An xinetd internal service which generate characters.  The
# xinetd internal service which continuously generates characters until the
# connection is dropped.  The characters look something like this:
# !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefg
# This is the tcp version. 
service chargen
{
        disable         = yes
        type            = INTERNAL
        id              = chargen-stream
        socket_type     = stream
        protocol        = tcp
        user            = root
        wait            = no 
}

# This is the udp version. 
service chargen
{
        disable         = yes
        type            = INTERNAL
        id              = chargen-dgram
        socket_type     = dgram
        protocol        = udp
        user            = root
        wait            = yes 
}

我用过perl命令

perl -0777 -pe 's|(service chargen[^\^]+)disable\s+=\syes|\1disable=no|' /etc/xinetd.d/chargen 
but it is replacing at only one place.

# description: An xinetd internal service which generate characters.  The
# xinetd internal service which continuously generates characters until the
# connection is dropped.  The characters look something like this:
# !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefg
# This is the tcp version.
service chargen
{
        disable         = yes
        type            = INTERNAL
        id              = chargen-stream
        socket_type     = stream
        protocol        = tcp
        user            = root
        wait            = no
}

# This is the udp version.
service chargen
{
        disable=no
        type            = INTERNAL
        id              = chargen-dgram
        socket_type     = dgram
        protocol        = udp
        user            = root
        wait            = yes
}

让它在两个地方都工作的正确命令是什么?

注意:我可以将 disable = yes 替换为 disable = no 而无需匹配 service chargen 但我需要使用相同的 sed/perl 命令替换 /etc/xinetd.conf 中也将有其他服务。

更新 正如 Jonathan 在他的评论中强调的那样,disable 可以在花括号内的任何位置。

最佳答案

使用 sed,您可以使用:

sed -e '/^service chargen/,/^}/ { /disable *= yes/ s/yes/no/; }'

第一部分搜索从service chargen开始到之后以开头的第一行的行范围;在该范围内,它查找包含 disable = yesdisable= yes 之间有任意数量空格的行,并更改 yesno。如有必要,您可以使正则表达式更加复杂(没有尾随空格;不要编辑 service chargen2018 block ,要求 } 没有尾随空格,等等)但它可能没有必要。

您通常可以进行就地编辑,但要注意系统之间在执行方式语义方面的差异。 (BSD和macOS需要-i '';GNU只需要-i;都接受-i.bak,两者意思相同— 但你有一个备份文件要清理。)

关于regex - Perl/Sed 命令多次替换相同的模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54853893/

相关文章:

perl - 对 Math::BigFloat 数字进行舍入

regex - 如果正则表达式和字符串都是变量,如何在 perl 中使用正则表达式

linux - 删除重复行但保留前 2 个实例

linux - 根据格式从文件中批量提取行

javascript - 组合两个正则表达式

javascript - 正则表达式匹配所有具有两个或更多字符的html标签,但ul和ol以及其中的列表项

jquery - Perl Catalyst - 从 AJAX POST 请求获取 JSON 数据

C-Linux-如何将C参数值发送给awk脚本?

java - 需要根据 ASCII 和 BASE64 编码的 UTF-8 字符串验证域的帮助

regex - 从字母数字字符串中查找并提取恰好 'n' 个连续连续数字的字符串