Я пытаюсь настроить мой файл pacman.conf автоматически при установке Arch с archiso.

Для этого я хочу раскомментировать две строки в файле конфигурации 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]. Как я могу это сделать?

1
Ben 1 Май 2019 в 12:04

3 ответа

Лучший ответ

Когда вы найдете строку #[multilib], прочитайте новую строку AND , добавьте ее в пробел и удалите # после строки (\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} $0=="#[multilib]"{f=1} 1' file

Таким образом, вам не нужно избегать регулярных выражений.

3
oguz ismail 1 Май 2019 в 11:44

Существует более простое решение 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
2
Alex Harvey 1 Май 2019 в 10:25

Sed предназначен для выполнения s / old / new для отдельных строк, вот и все. С awk:

$ awk '$0=="#[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 '$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
2
Ed Morton 1 Май 2019 в 19:05