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

Cae*_*lan 4 sed

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

...
admin_users = alice, bob
admin_groups = accounting, finance
...
Run Code Online (Sandbox Code Playgroud)

我想将用户追加到admin_users行,如果该行尚不存在。

据我了解,我基本上需要将两个条件组合起来...

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

我已尝试使用Google搜索功能,但找不到任何相关内容。如果可能的话,语法和简短说明将不胜感激。

Joh*_*024 5

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

$ cat file
...
admin_users = alice, bob
admin_users = alice, charlieston
admin_users = alice, charlie, bob
admin_users = alice, bob, charlie
admin_groups = accounting, finance
...
Run Code Online (Sandbox Code Playgroud)

总而言之,前两个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
...
Run Code Online (Sandbox Code Playgroud)

怎么运行的

  • -r

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

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

    如果admin_users已经有charlie逗号或行尾,则按p原样打印,然后删除,d这样就不会再应用任何命令了。

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

    如果我们到这里,那意味着那charlie还没有上线。因此,我们补充charlie到最后。

Mac OSX

以上已在GNU上进行了测试sed。对于OSX / BSD sed,请尝试:

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

变异

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

sed '/^admin_users\>/ {/\<charlie\>/! s/$/, charlie/}' file
Run Code Online (Sandbox Code Playgroud)

这将选择以开头的行admin_users,然后,仅当该行不包含时charlie,才进行替换。 \<\>是正则表达式,表示单词的开头或结尾。它们至少受GNU sed支持。