如何用sed取消注释下一行

How to uncomment the next line with sed

我正在尝试在使用 archiso 安装 Arch 时自动自定义我的 pacman.conf 文件。

为此,我想取消 pacman 配置文件中两行的注释。

这是相关文件的摘录:

#[multilib-testing]
#Include = /etc/pacman.d/mirrorlist

#[multilib]
#Include = /etc/pacman.d/mirrorlist

所以我想取消注释 multilib 块的两行,而不是 multilib-testing 块!

使用 sed 很容易取消注释块的第一行:

sed -i 's/#\[multilib]/\[multilib]/g' /etc/pacman.conf

然而,下一行与前一个块中的行完全相同(实际上在许多其他块中也是如此),所以如果我这样做:

sed -i 's/#Include =/Include =/g' pacman.conf

它将更改与该模式匹配的所有行。

我想要的是只更改[multilib]之后的特定行 我该怎么做?

当您找到 #[multilib] 行时,读取 N 行并将其附加到模式 space 中,然后删除后面的 #换行 (\n).

sed '/^#\[multilib]/{N;s/\n#/\n/}' file

给定您的示例其输出:

#[multilib-testing]
#Include = /etc/pacman.d/mirrorlist

#[multilib]
Include = /etc/pacman.d/mirrorlist

如果也是一个选项:

awk 'f{sub(/^#/,"");f=0} [=12=]=="#[multilib]"{f=1} 1' file

这样您就不需要转义正则表达式激活的字符。

有一个更简单的 sed 解决方案,不需要任何多行技术:

/^#\[multilib]/ {   # Match only the [multilib] line.
  n                 # Then read the next line.
  s/^#//            # ... and delete the comment marker.
}

测试:

▶ cat > FILE <<EOF
#[multilib-testing]
#Include = /etc/pacman.d/mirrorlist

#[multilib]
#Include = /etc/pacman.d/mirrorlist
EOF
▶ gsed -i '/^#\[multilib]/{n;s/^#//}' FILE

输出:

▶ cat FILE
#[multilib-testing]
#Include = /etc/pacman.d/mirrorlist

#[multilib]
Include = /etc/pacman.d/mirrorlist

sed 用于对单个字符串执行 s/old/new,仅此而已。使用 awk:

$ awk '[=10=]=="#[multilib]"{c=2} c&&c--{sub(/#/,"")} 1' file
#[multilib-testing]
#Include = /etc/pacman.d/mirrorlist

[multilib]
Include = /etc/pacman.d/mirrorlist

不需要转义字符,如果您需要从 50 行而不是 2 行中删除 #,您只需将 2 更改为 50,您不必重写脚本!如果愿意,您显然可以参数化开始字符串和要取消注释的行数:

$ awk -v beg='#[multilib]' -v num=2 '[=11=]==beg{c=num} c&&c--{sub(/#/,"")} 1' file
#[multilib-testing]
#Include = /etc/pacman.d/mirrorlist

[multilib]
Include = /etc/pacman.d/mirrorlist

$ awk -v beg='#[multilib-testing]' -v num=2 '[=11=]==beg{c=num} c&&c--{sub(/#/,"")} 1' file
[multilib-testing]
Include = /etc/pacman.d/mirrorlist

#[multilib]
#Include = /etc/pacman.d/mirrorlist

$ awk -v beg='#[multilib-testing]' -v num=5 '[=11=]==beg{c=num} c&&c--{sub(/#/,"")} 1' file
[multilib-testing]
Include = /etc/pacman.d/mirrorlist

[multilib]
Include = /etc/pacman.d/mirrorlist