0

Как добавить строку текста в середину файла с помощью bash?

19

Я пытаюсь добавить строку текста в середину текстового файла с помощью 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 ответ(ов)

0

Вот решение с использованием sed:

$ sed -n 'H;${x;s/^\n//;s/nameserver .*$/nameserver 127.0.0.1\n&/;p;}' resolv.conf

Как это работает:

  1. Подавление вывода: сначала мы подавляем вывод sed с помощью флага -n.

  2. Добавление строк в удерживающее пространство: для каждой строки мы добавляем её в удерживающее пространство, разделяя строки переводом строки:

    H
    
  3. Перемещение содержимого удерживающего пространства в рабочее: когда мы доходим до конца файла ($), мы переносим содержимое удерживающего пространства в рабочее пространство:

    x
    
  4. Удаление первой пустой строки: если первая строка в рабочем пространстве пустая, мы заменяем её на ничего:

    s/^\n//
    
  5. Замена первой строки, начинающейся с nameserver: затем мы заменяем первую строку, которая начинается с nameserver, на строку, содержащую nameserver 127.0.0.1, перевод строки (ваша версия sed может не поддерживать \n, в таком случае замените n на реальный перевод строки) и исходную строку (представленную символом &):

    s/nameserver .*$/nameserver 127.0.0.1\n&/
    
  6. Вывод результата: теперь нам просто нужно напечатать результат:

    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

Если у вас есть дополнительные вопросы или вам нужно больше информации, не стесняйтесь спрашивать!

0

Если вы хотите вставить строку сразу после строки search, это намного проще:

sed -ie '/^search/a nameserver 127.0.0.1' filename
  • -i : редактирует файл на месте
  • -e : позволяет выполнять скрипт/команды внутри выражения sed
  • a mynewtext : команда, которая говорит sed вставить текст mynewtext после совпадающего шаблона
0

Этот код на awk выполняет поиск строк, начинающихся с nameserver, и в случае, если переменная modif равна 0 (или не установлена), он выводит слово "INSERT" перед этой строкой и устанавливает modif в 1, чтобы в дальнейшем не добавлять "INSERT" повторно. Все остальные строки выводятся без изменений.

Вот краткий разбор:

  • awk '/^nameserver/ && !modif — проверяет, начинается ли строка с nameserver и не была ли уже выполнена вставка INSERT.
  • { printf("INSERT\n"); modif=1 } — если вышеуказанные условия соблюдены, выводит "INSERT" и устанавливает modif в 1, чтобы избежать повторной вставки.
  • {print} — выводит текущую строку в любом случае.

Таким образом, это полезно, например, для обработки конфигурационных файлов, где требуется обозначить первый nameserver в списке каким-то специальным маркером.

0

Вот решение на 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 уже была найдена.

0

Это может вам подойти:

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. Убедитесь, что у вас есть резервная копия файла перед его редактированием.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь