我试图在脚本中编辑一个配置文件,有几行,但格式基本上是:
...
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
,它确保charlie2
或bigcharlie
不匹配。
如果确定该行不包含术语charlie,则s/$/, charlie
命令会将, charlie
附加到$
行的末尾。
在MacOS上,字边界的b
将不起作用。您需要使用[[:<:]]
作为左边界,使用[[:>:]]
作为右边界。命令看起来像:
sed '/^admin_users/{/[[:<:]]charlie[[:>:]]/!s/$/, charlie/}' input