sed双条件?匹配包含文本的行首,然后追加



我试图在脚本中编辑一个配置文件,有几行,但格式基本上是:

...
admin_users = alice, bob
admin_groups = accounting, finance
...

如果admin_users行中还不存在用户,我想在该行中添加一个用户。

据我所知,我基本上需要将两个条件句结合起来。。。

/^admin_users/s/$/, charlie/=将, charlie添加到以admin_users开头的行/charlie/!s/$/, charlie/=将, charlie附加到不包含charlie的行

我试过在谷歌上搜索,但找不到任何相关的东西。如果这是可能的,语法和简短的解释将不胜感激。

要捕获更多特殊情况,让我们使用以下测试文件:

$ cat file
...
admin_users = alice, bob
admin_users = alice, charlieston
admin_users = alice, charlie, bob
admin_users = alice, bob, charlie
admin_groups = accounting, finance
...

总之,前两个admin_users需要添加charlie。第二个两个已经有他了。

仅当charlie不在时添加:

$ sed -r '/^admin_users .*, charlie(,|$)/{p;d}; /^admin_users / s/$/, charlie/' file
...
admin_users = alice, bob, charlie
admin_users = alice, charlieston, charlie
admin_users = alice, charlie, bob
admin_users = alice, bob, charlie
admin_groups = accounting, finance
...

它的工作原理

  • -r

    使用扩展的正则表达式,而不是基本的正则表达式。(在OSX/BSD上,请改用-E。)

  • /^admin_users .*, charlie(,|$)/{p;d}

    如果一个admin_users已经有charlie后跟逗号或行尾,则按原样打印p并删除d,这样就不会对其应用其他命令。

  • /^admin_users / s/$/, charlie/

    如果我们到了这里,这意味着charlie还没有上线。因此,我们将charlie添加到末尾。

Mac OSX

以上内容在GNUsed上进行了测试。对于OSX/BSDsed,请尝试:

sed -E -e '/^admin_users .*, charlie(,|$)/{p;d;}' -e '/^admin_users / s/$/, charlie/' file

一种变体

正如Glenn Jackman所建议的,这里有另一种方法:

sed '/^admin_users>/ {/<charlie>/! s/$/, charlie/}' file

这选择以admin_users开始的行thta,然后,仅当该行不包含charlie时,才进行替换。CCD_ 24和CCD_ 25是正则表达式,表示单词的开头或结尾。它们至少得到GNU sed的支持。

有了GNUsed,我会使用这个:

sed '/^admin_users/{/bcharlieb/!s/$/, charlie/}' input

解释:

/^admin_users/搜索以admin_users开头的行,并将大括号{}之间的以下块应用于该行。CCD_ 30检查该行是否不包含字CCD_。注意单词边界b,它确保charlie2bigcharlie不匹配。

如果确定该行不包含术语charlie,则s/$/, charlie命令会将, charlie附加到$行的末尾。


在MacOS上,字边界的b将不起作用。您需要使用[[:<:]]作为左边界,使用[[:>:]]作为右边界。命令看起来像:

sed '/^admin_users/{/[[:<:]]charlie[[:>:]]/!s/$/, charlie/}' input

相关内容

最新更新