我有一个配置文件我尝试在脚本中编辑,有几行,但格式基本上是:
...
admin_users = alice, bob
admin_groups = accounting, finance
...
我想将用户附加到admin_users行,如果他们在该行上已不存在。
据我了解,我基本上需要结合两个条件......
/^admin_users/s/$/, charlie/
=将, charlie
添加到以admin_users
开头的行
/charlie/!s/$/, charlie/
=将, charlie
附加到不包含charlie
我试过谷歌搜索但我找不到相关的东西。如果可能的话,将非常感谢语法和简短的解释。
答案 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
添加到最后。
以上是在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
,以确保charlie2
或bigcharlie
不匹配。
如果确定该行不包含术语charlie,则s/$/, charlie
命令会将, charlie
附加到行$
的末尾。
在MacOS上,单词边界的\b
将不起作用。您需要使用[[:<:]]
作为左边界,[[:>:]]
作为右边界。该命令看起来像:
sed '/^admin_users/{/[[:<:]]charlie[[:>:]]/!s/$/, charlie/}' input