如何更改精确行的分隔符之间的一组字符?

如何更改精确行的分隔符之间的一组字符?

我正在尝试编写一个脚本来更改 dovecot 用户数据库中的用户密码,但我无法理解如何用sed.

例如,请检查这一行(这是来自 dovecot userdb 的部分):

[email protected]:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNa‌​XqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::
[email protected]:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNa‌​XqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/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脚本中移出任何不匹配的行来验证匹配,但如果任何行通过其匹配测试,它也会在保存变量位以供下一次替换!方面发挥双重作用。而且,所有后续命令也只能在与起始地址匹配的行上执行。\1s///

当然,还有一种不太终极的形式,它用花括号指定匹配函数上下文:

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$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNa‌​XqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::
  • 我使用awk它的-F选项将冒号()设置:为字段分隔符,如果行开始(^)则用新值()[email protected]替换column2( ) 。$2NEWPASSWODHERE

  • OFS=':'将输出字段分隔符从空格(默认)更改为冒号(:)。

  • 最后1,默认启用打印。

相关内容