Нужна помощь в sed с использованием шаблона для создания новых файлов для виртуальных хостов

for j in `cat server_name_list`; do sed -i 's/DIR/${j}/g' dlist1 > $j.conf; done

В основном я пытаюсь создать несколько виртуальных хостов apache, используя один файл виртуального хоста в качестве шаблона....

Итак, файл шаблона: кошка /tmp/dlist1

Allow From All
DocumentRoot /var/www/html/DIR
ServerName DIR.com
ServerAlias www.DIR.com
DirectoryIndex index.html index.htm
ErrorLog "logs/DIR_com_error_log"
CustomLog "logs/DIR_com_access_log" common

И список серверов находится в файле

cat /tmp/server_name_list
abc.com
xyz.com
utv.com

поэтому скрипт sed должен дать мне три файла, как в abc.conf, xyz.conf, utv.conf

с этим содержанием (просто напишите здесь для «abc»):

Allow From All
DocumentRoot /var/www/html/abc
ServerName abc.com
ServerAlias www.abc.com
DirectoryIndex index.html index.htm
ErrorLog "logs/abc_com_error_log"
CustomLog "logs/abc_com_access_log" common

🤔 А знаете ли вы, что...
С Bash можно создавать условные выражения и скрипты, которые реагируют на различные события.


68
4

Ответы:

Решено

Ну вот:

for j in `cat server_name_list`; do
  j = "${j%.*}"
  sed "s/DIR/$j/g" dlist1 > $j.conf;
done

Объяснение:

  • j = "${j%.*} использует расширение параметра, чтобы удалить расширение .com из имени сервера. Синтаксис ${j%.*} означает удаление кратчайшего совпадения .* (т. е. «.com») с конца строки j.
  • sed "s/DIR/$j/g" dlist1 > $j.conf заменяет все вхождения строки DIR в файле шаблона dlist1 на текущее имя сервера j
  • Вывод команды sed перенаправляется в файл с именем $j.conf.

Надеюсь, это поможет 👍


Сначала ты DRLWF

Решение с петлей while + read. Что-то вроде:

#!/usr/bin/env bash

while IFS= read -ru "$fd" servers; do
  sed "/^\(ServerName\) .*/s//\1 $servers/" dlist1 > "${servers%.*}"
done {fd}< server_name_list
exec {fd}<&-

  • Настройте/используйте абсолютный путь для используемых файлов.

Я бы использовал GNU AWK для этой задачи следующим образом, пусть temp.txt контент будет

Allow From All
DocumentRoot /var/www/html/DIR
ServerName DIR.com
ServerAlias www.DIR.com
DirectoryIndex index.html index.htm
ErrorLog "logs/DIR_com_error_log"
CustomLog "logs/DIR_com_access_log" common

и list.txt содержание быть

abc.com
xyz.com
utv.com

затем

awk 'BEGIN{FS = "[.]";RS = "";getline template < "temp.txt";RS = "\n"}{print gensub(/DIR/,$1,"g",template) > $1 ".conf";close($1 ".conf")}' list.txt

создает файлы

abc.conf
utv.conf
xyz.conf

содержание 1-го из них

Allow From All
DocumentRoot /var/www/html/abc
ServerName abc.com
ServerAlias www.abc.com
DirectoryIndex index.html index.htm
ErrorLog "logs/abc_com_error_log"
CustomLog "logs/abc_com_access_log" common

Объяснение: я сообщаю GNU AWK, что буквенная точка является разделителем полей (FS), затем я отключаю режим абзаца, устанавливая RS пустую строку, но только во время использования getline , чтобы он читал все до первой пустой строки, затем я установите RS на новую строку, чтобы это работало обычным образом. Затем для каждой строки я использую функцию gensub, мне не нужна там группа захвата, но я использую ее, поскольку хочу, чтобы значение переменной template оставалось нетронутым, после замены всех (g) DIR вхождений значением 1-го столбца я print это в файл с соответствующим именем и close этот файл.

(проверено в GNU Awk 5.0.1)


Это может сработать для вас (GNU sed и parallel):

parallel sed 's/DIR/{.}/g' templateFile \> {.}.conf :::: serversFile

Для каждой строки в файле серверов примените изменения к файлу шаблона и сохраните результаты в отдельном файле.

Н.Б. {.} возвращает строку из файла серверов за вычетом расширения, например. abc.com становится abc.