Как добавить строку текста в середину файла с помощью bash?
Я пытаюсь добавить строку текста в середину текстового файла в bash script. В частности, я пытаюсь добавить сервер имен в файл /etc/resolv.conf. Как бы то ни было, resolv.conf выглядит так:
# Generated by NetworkManager
domain dhcp.example.com
search dhcp.example.com
nameserver 10.0.0.1
nameserver 10.0.0.2
nameserver 10.0.0.3
Моя цель состоит в том, чтобы добавить nameserver 127.0.0.1
выше всех других строк сервера имен, но ниже любого текста выше этого. В конце я хочу, чтобы мой файл resol.conf выглядел следующим образом:
# Generated by NetworkManager
domain dhcp.example.com
search dhcp.example.com
nameserver 127.0.0.1
nameserver 10.0.0.1
nameserver 10.0.0.2
nameserver 10.0.0.3
Как это возможно с помощью bash script? Это что-то sed или awk? Или будет ли творческий greping для воссоздания файла лучшим моментом?
Ответы
Ответ 1
Вот решение, использующее sed:
$ sed -n 'H;${x;s/^\n//;s/nameserver .*$/nameserver 127.0.0.1\n&/;p;}' resolv.conf
# Generated by NetworkManager
domain dhcp.example.com
search dhcp.example.com
nameserver 127.0.0.1
nameserver 10.0.0.1
nameserver 10.0.0.2
nameserver 10.0.0.3
Как это работает: во-первых, подавить вывод sed с помощью флага -n
. Затем для каждой строки добавим строку в пространство удержания, разделив их на строки новой строки:
H
Когда мы подходим к концу файла (адресуем $
), мы перемещаем содержимое пространства удержания в пространство рисунка:
x
Если первая строка в пространстве шаблонов пуста, мы ничего не заменим.
s/^\n//
Затем мы заменяем первую строку, начиная с nameserver
линией, содержащей nameserver 127.0.0.1
, новую строку (ваша версия sed
может не поддерживать \n
, и в этом случае заменить n
на литерал newline) и исходной линией (представленной &
):
s/nameserver .*$/nameserver 127.0.0.1\n&/
Теперь нам просто нужно распечатать результаты:
p
Ответ 2
Предполагая, что вы хотите вставить сразу после строки search
, это намного проще:
sed -ie '/^search/a nameserver 127.0.0.1' filename
-
-i
: редактировать файл на месте
-
-e
: позволяет выполнять команды script/внутри выражения sed
-
a mynewtext
: команда, которая сообщает sed вставить текст mynewtext после сопоставленного шаблона
Ответ 3
awk '/^nameserver/ && !modif { printf("INSERT\n"); modif=1 } {print}'
Ответ 4
Как насчет чего-то типа:
sed -e ':a;N;$!ba;s/nameserver/nameserver 127.0.0.1\nnameserver/' /etc/resolv.conf
(аналогично этому: sed: найдите шаблон поверх двух строк, а не замените его после этого шаблона)
Ответ 5
Это может сработать для вас:
sed -e '/nameserver/{x;/./b;x;h;i\nameserver 127.0.0.1' -e '}' resolv.conf
Или GNU sed:
sed -e '0,/nameserver/{//i\nameserver 127.0.0.1' -e '}' resolv.conf
Ответ 6
Здесь решение Perl:
perl -lne 'if (not $f and /^nameserver/){ print "nameserver 127.0.0.1"; $f=1 }; print' resolv.conf
-
-n
перемещаться по каждой строке входного файла, не печатать автоматически каждую строку
-
-l
удаляет символы новой строки перед обработкой и добавляет их обратно
-
-e
выполнить код perl
$f
используется как флаг, указывающий, что строка сервера имен уже найдена