I'm trying to customize my pacman.conf file automatically when installing Arch with archiso.

For that, I want to uncomment two lines in the pacman configuration file.

Here is an extract from the file in question:

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

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

So I want to uncomment the two lines of the multilib block, but not the multilib-testing block!

To uncomment the first line of the block is easy with sed:

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

However, the next line is exactly the same as the one in the previous block (and in many other blocks in practice), so if I do:

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

It's going to change all the line matching the pattern.

What I want is to only change the specific line just after [multilib] How can I do that?

3 Answers

3
oguzismail On Best Solutions

When you find #[multilib] line, read a New line and append it to pattern space, and remove # coming after a line feed (\n).

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

Given your sample its output:

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

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

If is also an option:

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

This way you don't need to escape regex-active characters.

2
Shyam Pillai On

There is a simpler sed solution that doesn't require any multiline techniques:

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

Testing:

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

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

Output:

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

#[multilib]
Include = /etc/pacman.d/mirrorlist
2
Ed Morton On

sed is for doing s/old/new on individual strings, that is all. With awk:

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

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

No escaping characters required and if you need to remove the # from 50 lines instead of 2 you just change 2 to 50, you don't have to rewrite your script! You can obviously parameterize the beginning string and the number of lines to uncomment if you like:

$ awk -v beg='#[multilib]' -v num=2 '$0==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 '$0==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 '$0==beg{c=num} c&&c--{sub(/#/,"")} 1' file
[multilib-testing]
Include = /etc/pacman.d/mirrorlist

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