Удаление части текстового файла и последующих строк с помощью sed

8

Мне нужно отредактировать файл следующим образом:

auto wlx00
allow-hotplug wlx00
iface wlx000 inet dhcp
iface wlx000 inet6 auto
  post-up sysctl -w net.ipv6.conf.wlx000.accept_ra=2
auto wlx000

цель состоит в том, чтобы удалить строки, начинающиеся с 'iface ... inet6', а также удалить следующие несколько, которые начинаются с пробела (может быть ни одного или больше чем один):

iface wlx000 inet6 auto
  post-up sysctl -w net.ipv6.conf.wlx000.accept_ra=2

и оставьте нетронутым для следующего результата:

auto wlx00
allow-hotplug wlx00
iface wlx000 inet dhcp
auto wlx000

Я попытался с помощью Sed следующим образом:

sed -i.old -r -e "/iface\s*\w*\s*inet6.*/,\${d;/^\s.*/d;}" /etc/configfile

но он удаляет все, начиная с нужного места, но стирая до конца. Я просто хочу удалить строки, начинающиеся с пробела после текста select iface.

ТСМ
источник
1
@fcm, пожалуйста, дайте нам знать, если решения ниже в порядке. если нет, мы можем настроить его для вас
1
@ ТНТ не тот же вопрос. Это НЕ для удаления одной строки, это удалить строку плюс следующие строки, начиная с пробела.
18.30
2
Теоретически дубликат, но не на практике - я думаю, что было бы хорошо дать здесь отдельный ответ, который демонстрирует, как сопоставить данный шаблон с последующими строками, которые имеют начальные пробелы.
Джефф Шаллер
1
@rudic предоставил отличный и тщательно продуманный ответ, который далек от простого поиска и удаления, ничего из предложенного дубликата не приближается к этому.
Fcm

Ответы:

7

Попробуйте эту адаптацию вашего sedодного лайнера:

sed  '/iface\s*\w*\s*inet6.*/,/^[^ ]/ {/^[^ i]/!d}' file

Он соответствует диапазону от вашего первого шаблона до первой строки, НЕ начинающейся с пробела, и удаляет строки, начинающиеся с пробела или «i» (для ведущего iface). Необходимо переосмыслить, если iпотребуется после блока.

Похоже, это работает:

sed -n '/iface\s*\w*\s*inet6.*/ {:L; n; /^[ ]/bL;}; p' file

Пожалуйста, попробуйте и доложите.

Рудик
источник
6

Скрипт для стандарта, sedкоторый использует явный цикл для удаления строк:

/^iface .* inet6/ {
    :again
    N
    s/.*\n//
    /^[[:blank:]]/b again
}

Сценарий находит inet6строки, а затем добавляет следующую строку к этой строке внутри пространства шаблона (со встроенным символом новой строки между ними). Затем он удаляет пространство шаблона вплоть до первого символа новой строки (это удаляет исходную inet6строку). Это продолжается до тех пор, пока пробел не начинается с пустого символа (пробел или табуляция).

Тестирование:

$ cat file
auto wlx00
allow-hotplug wlx00
iface wlx000 inet dhcp
iface wlx000 inet6 auto
  post-up sysctl -w net.ipv6.conf.wlx000.accept_ra=2
auto wlx000
$ sed -f script.sed <file
auto wlx00
allow-hotplug wlx00
iface wlx000 inet dhcp
auto wlx000

Тестирование на искусственных данных:

$ cat file
something1
something2
iface have a inet6 here
   delete me
   me too
   same here
something3
something4
iface more something inet6
   be gone
   skip this
something5
$ sed -f script.sed <file
something1
something2
something3
something4
something5

Скрипт в виде «однострочника»:

sed -e '/^iface .* inet6/ {' -e ':a' -e 'N;s/.*\n//;/^[[:blank:]]/ba' -e '}'
Кусалананда
источник
3

У вас уже есть хорошие ответы на sedинструмент, но позвольте мне предложить другой, я полагаю, гораздо более простой, подход с использованием pcregrep:

pcregrep -Mv '^iface.*inet6(.|\n )*' file

Регулярное выражение должно быть самоочевидным - мы ищем шаблон, начиная со строки, ^iface.*inet6а затем группу любого символа ИЛИ новую строку, за которой следует один пробел, повторяемый ноль или более раз. Тогда нам просто нужно дать pcregrepразрешение на многолинейное сопоставление с -Mопцией и полностью изменить все на -v(подобранная часть будет удалена).

jimmij
источник
Я обычно предпочитаю использовать pcregrep, гораздо более интуитивно понятный.
Руи Ф Рибейро