Как добавить строку текста в середину файла с помощью bash?
Я пытаюсь добавить строку текста в середину текстового файла с помощью bash-скрипта. Конкретно, я хочу добавить адрес nameserver в файл /etc/resolv.conf. На данный момент файл resolv.conf выглядит следующим образом:
# Сгенерировано 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
выше всех других строк с nameserver, но ниже любого текста, находящегося выше. В итоге я хочу, чтобы файл resolv.conf выглядел так:
# Сгенерировано 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-скрипта? Может быть, это могут сделать команды sed или awk? Или стоит использовать креативный grep для воссоздания файла?
5 ответ(ов)
Вот решение с использованием sed
:
$ sed -n 'H;${x;s/^\n//;s/nameserver .*$/nameserver 127.0.0.1\n&/;p;}' resolv.conf
Как это работает:
Подавление вывода: сначала мы подавляем вывод
sed
с помощью флага-n
.Добавление строк в удерживающее пространство: для каждой строки мы добавляем её в удерживающее пространство, разделяя строки переводом строки:
H
Перемещение содержимого удерживающего пространства в рабочее: когда мы доходим до конца файла (
$
), мы переносим содержимое удерживающего пространства в рабочее пространство:x
Удаление первой пустой строки: если первая строка в рабочем пространстве пустая, мы заменяем её на ничего:
s/^\n//
Замена первой строки, начинающейся с
nameserver
: затем мы заменяем первую строку, которая начинается сnameserver
, на строку, содержащуюnameserver 127.0.0.1
, перевод строки (ваша версияsed
может не поддерживать\n
, в таком случае замените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
Если у вас есть дополнительные вопросы или вам нужно больше информации, не стесняйтесь спрашивать!
Если вы хотите вставить строку сразу после строки search
, это намного проще:
sed -ie '/^search/a nameserver 127.0.0.1' filename
-i
: редактирует файл на месте-e
: позволяет выполнять скрипт/команды внутри выражения seda mynewtext
: команда, которая говорит sed вставить текст mynewtext после совпадающего шаблона
Этот код на awk
выполняет поиск строк, начинающихся с nameserver
, и в случае, если переменная modif
равна 0 (или не установлена), он выводит слово "INSERT" перед этой строкой и устанавливает modif
в 1, чтобы в дальнейшем не добавлять "INSERT" повторно. Все остальные строки выводятся без изменений.
Вот краткий разбор:
awk '/^nameserver/ && !modif
— проверяет, начинается ли строка сnameserver
и не была ли уже выполнена вставкаINSERT
.{ printf("INSERT\n"); modif=1 }
— если вышеуказанные условия соблюдены, выводит "INSERT" и устанавливаетmodif
в 1, чтобы избежать повторной вставки.{print}
— выводит текущую строку в любом случае.
Таким образом, это полезно, например, для обработки конфигурационных файлов, где требуется обозначить первый nameserver
в списке каким-то специальным маркером.
Вот решение на Perl:
perl -lne 'if (not $f and /^nameserver/){ print "nameserver 127.0.0.1"; $f=1 }; print' resolv.conf
-n
: цикл по каждой строке входного файла, не печатает строки автоматически.-l
: удаляет символы новой строки перед обработкой и добавляет их обратно после.-e
: выполняет указанный код Perl.
Переменная $f
используется как флаг для указания того, что строка с nameserver
уже была найдена.
Это может вам подойти:
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
Эти команды заменяют существующую строку nameserver
в файле resolv.conf
на nameserver 127.0.0.1
. Убедитесь, что у вас есть резервная копия файла перед его редактированием.
Bash инструмент для получения n-й строки из файла
Как использовать 'grep' для непрерывного потока?
Как выполнить рекурсивный поиск/замену строки с помощью awk или sed?
Можно ли использовать awk для преобразования всех строчных букв в заглавные?
Существует ли аналог 'git sed'?