仅在包含另一个模式的另一行之后的第一次出现中替换包含模式的行

Posted

技术标签:

【中文标题】仅在包含另一个模式的另一行之后的第一次出现中替换包含模式的行【英文标题】:replace a line containing pattern only in the first occurrence after another line that contains another pattern 【发布时间】:2022-01-11 23:47:45 【问题描述】:

我想用 sed 替换文件中包含匹配模式 ForwardX11 的行,但只想在包含它的行是在包含另一个模式的另一行之后找到的第一行时替换它。

例子:

Host *
#    ForwardAgent no
#    ForwardX11 no
#    ForwardX11Trusted no
#    AnotherLine no

Host localhost
    ForwardX11 yes

在上面的示例中,我只想将行 # ForwardX11 no 替换为 Forward yes,因为此行是行 Host * 之后的第一行。但我想在Host localhost 行之后保持 Forward yes 行不变。

到目前为止,我尝试像这样使用 sed:

sed -i "/ForwardX11Trusted/! s/.*ForwardX11.*/    ForwardX11 yes/" /etc/ssh/ssh_config

但它也改变了第二行(Host localhost 之后的 ForwardX11)。

EDIT 1:假设我不知道包含模式ForwardX11 的行是否在开头有#,也不知道ForwardX11 是否设置为是或否。

编辑 2:不一定要用 sed 来完成。

【问题讨论】:

's/# ForwardX11 no/ Forward yes/' 我不知道包含模式'ForwardX11'的行是否有#开头,也不知道ForwardX11设置为yes还是no。 【参考方案1】:

使用sed

$ sed -i.bak '/^Host \*/,/ForwardX11/ s/#\?\(.*X11\) no/\1 yes/' /etc/ssh/sshd_config
Host *
#    ForwardAgent no
    ForwardX11 yes
#    ForwardX11Trusted no
#    AnotherLine no

Host localhost
    ForwardX11 yes

【讨论】:

【参考方案2】:

必须被sed吗?使用 awk 更容易(IMO)

awk '
    $1 == "Host" in_block = $2 == "*"
    in_block && $2 == "ForwardX11" print "    ForwardX11 yes"; next
    1
' ssh_config
Host *
#    ForwardAgent no
    ForwardX11 yes
#    ForwardX11Trusted no
#    AnotherLine no

Host localhost
    ForwardX11 yes

【讨论】:

不,它不必用 sed... 很好的答案

以上是关于仅在包含另一个模式的另一行之后的第一次出现中替换包含模式的行的主要内容,如果未能解决你的问题,请参考以下文章

用bash中的另一个文件替换整个文件

SQL:Regexp_replace 但仅在值第一次出现在记录中时

seaborn gridplot/subplots 在第一列显示一个变量,在第二列显示同一行 ID 的另一个变量

将字符串与通配符模式匹配的递归函数

使用 sed 在第 N 个匹配模式之后插入一些文本

编辑时如何用导航控制器中的另一个 UIBarButtonItem 替换后退按钮?