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

时间:2015-04-10 17:57:41

标签: sed

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

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

我想将用户附加到admin_users行,如果他们在该行上已不存在。

据我了解,我基本上需要结合两个条件......

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

的行

我试过谷歌搜索但我找不到相关的东西。如果可能的话,将非常感谢语法和简短的解释。

2 个答案:

答案 0 :(得分: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
...

总之,前两个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

以上是在GNU sed上测试的。对于OSX / BSD sed,请尝试:

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开头的行,然后,只有当行不包含charlie时,才进行替换。 \<\>是正则表达式,表示单词的开头或结尾。他们至少得到GNU sed。

的支持

答案 1 :(得分:1)

拥有GNU sed我会用这个:

sed '/^admin_users/{/\bcharlie\b/!s/$/, charlie/}' input

<强>解释

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

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


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

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