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

pow*_*ash 4 sed text-processing

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

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

123@example.com:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNa??XqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::
abc@example.com:{SHA512-CRYPT}$6$0vthg.LubtSCxRRK$MdTKNQ2Vk8ZW3XQXNXStt9rfr6fNa??XqPvZ0o9WJ8mW8y9ozE1pi8dYM8oQzwWa8ESGzEmJO6yT/tgi3ZEqAiE0:::
Run Code Online (Sandbox Code Playgroud)

如何仅针对用户“123@example.com”而不是用户“abc@example.com”使用sed替换以“{SHA512-CRYPT}”开头的“:”分隔符之间的字符串?

Run*_*ium 8

也许:

sed 's/\(\(^\|:\)123@example\.com:\)\([^:]\+\)/\1foo/'
Run Code Online (Sandbox Code Playgroud)

鉴于值中没有转义分隔符。

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
Run Code Online (Sandbox Code Playgroud)
  • A: s/ 替换命令。
  • B: (^|:)以行首或分隔符:、组 2、匹配组 1 的一部分开始。
  • C: 要匹配的用户,匹配组 1 的一部分。
  • D: ([^:]+)要删除的部分,直到:. 第 3 组的一部分。直到下一个分隔符的所有内容。也许应该是\(:\|$\),但它应该以:它结束就足够了。
  • E: \) 结束删除分组。
  • F: \1 放回匹配组 1。用户 + 分隔符。
  • G: foo 什么都将作为地穴插入。
  • H: /结束这一切。可选地是/g全局的,但假设它只是一次。


mik*_*erv 7

你可以在这里替换地址 -

sed '/^123@example.com:{SHA512-CRYPT}/s/{[^:]*/REPLACE/'
Run Code Online (Sandbox Code Playgroud)

这里s///替换命令是/regxp/地址的函数,因此s///除非该行首先匹配其父地址,否则甚至不会尝试替换。

或者只带一个s///

sed 's/^\(123@example.com:\){SHA512-CRYPT}[^:]*/\1REPLACE/'
Run Code Online (Sandbox Code Playgroud)

或者仅当 123 不紧跟冒号时才锚定到行首:

sed 's/^\(\(.*:\)*123@example.com:\){SHA512-CRYPT}[^:]*/\1REPLACE/'
Run Code Online (Sandbox Code Playgroud)

虽然我当然对复杂的子表达式并不陌生,但在这种情况下,这种事情是不必要的——我通常更喜欢地址形式,当我能得到它时——我发现它更容易阅读,更有效,而且完全可移植。诚然,乍一看,我似乎高估了这里固有的复杂性。

同样,您也可以拆分反向引用和实际替换,例如:

sed -e '
/^\(123@example.com:\){SHA512-CRYPT}[^:]*/!b
s//\1REPLACE/
#other commands that can be sure to affect only a line matching the 1st address'
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,地址通过b为任何!不匹配的行退出脚本来验证匹配,但如果任何行通过其匹配测试,它也会在保存变量位以\1供下一个s///替换时执行双重任务。此外,所有后续命令也只能在匹配初始地址的行上执行。

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

sed -e '
/^123@example.com:{SHA512-CRYPT}/{
    s/{[^:]*/REPLACE/
    #other function commands
};/other match function/{
    #still more commands...
}'
Run Code Online (Sandbox Code Playgroud)