我正在尝试编写一个脚本来更改 dovecot 用户数据库中的用户密码,但我无法理解如何用sed
.
例如,请检查这一行(这是来自 dovecot userdb 的部分):
[email protected]:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNaXqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::
[email protected]:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNaXqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::
如何仅针对用户“替换以“{SHA512-CRYPT}”开头的“:”分隔符之间的字符串[电子邮件受保护]“ 并且不适用于用户 ”[电子邮件受保护]“用 sed?
答案1
也许:
sed 's/\(\(^\|:\)123@example\.com:\)\([^:]\+\)/\1foo/'
鉴于值中没有转义分隔符。
sed 's/\(\(^\|:\)123@example\.com:\)\([^:]\+\)/\1foo/'
| | | | | | | |
| | | | | | | +----- H. End of sub.
| | | | | | +------- G. Sub string
| | | | | +---------- F. Match Group 1.
| | | | +------------ E. End of Group 3.
| | | +------------------ D. Group 3.
| | +----------------------------------- C. User
| +--------------------------------------------- B. Prefix Group 2.
+--------------------------------------------------- A. Substitute
A:
s/
替代命令。B:
(^|:)
从行开头或分隔符开始:
,组 2,匹配组 1 的一部分。C:
要匹配的用户,属于匹配组 1。D:
([^:]+)
要删除的部分,直到 的任何内容:
。第 3 组的一部分。直到下一个分隔符的所有内容。也许应该是\(:\|$\)
,但因为它应该以它结束,:
所以应该足够了。E:
\)
结束移除分组。F:
\1
放回匹配组 1。用户 + 分隔符。G:
foo
什么都将被插入作为地穴。H:
/
结束这一切。可选择/g
全局的,但假设它只是一次。
答案2
您可以在这里替换地址 -
sed '/^[email protected]:{SHA512-CRYPT}/s/{[^:]*/REPLACE/'
这里s///
ubstitution 命令是地址的函数/regxp/
,因此s///
除非该行首先与其父地址匹配,否则甚至不会尝试 ubstitution。
或者只是带有一个s///
:
sed 's/^\([email protected]:\){SHA512-CRYPT}[^:]*/\1REPLACE/'
或者仅当 123 不立即跟随冒号时才锚定到行首:
sed 's/^\(\(.*:\)*[email protected]:\){SHA512-CRYPT}[^:]*/\1REPLACE/'
虽然我对复杂的子表达式当然并不陌生,但在这种情况下,这样的事情是不必要的——当我能得到它时,我通常更喜欢地址形式——我发现它更容易阅读,更高效,并且完全可移植。但不可否认的是,乍一看,我似乎最初高估了这里固有的复杂性。
同样,您也可以将反向引用和实际替换分开,例如:
sed -e '
/^\([email protected]:\){SHA512-CRYPT}[^:]*/!b
s//\1REPLACE/
#other commands that can be sure to affect only a line matching the 1st address'
在上面的示例中,地址通过从b
脚本中移出任何不匹配的行来验证匹配,但如果任何行通过其匹配测试,它也会在保存变量位以供下一次替换!
方面发挥双重作用。而且,所有后续命令也只能在与起始地址匹配的行上执行。\1
s///
当然,还有一种不太终极的形式,它用花括号指定匹配函数上下文:
sed -e '
/^[email protected]:{SHA512-CRYPT}/{
s/{[^:]*/REPLACE/
#other function commands
};/other match function/{
#still more commands...
}'
答案3
使用awk
:
awk -F':' '/^[email protected]/ {$2="NEWPASSWORDHERE"}1' OFS=':' infile
[email protected]:NEWPASSWORDHERE:::
[email protected]:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNaXqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::
我使用
awk
它的-F
选项将冒号()设置:
为字段分隔符,如果行开始(^
)则用新值()[email protected]
替换column2( ) 。$2
NEWPASSWODHERE
OFS=':'
将输出字段分隔符从空格(默认)更改为冒号(:
)。最后
1
,默认启用打印。