Форум русскоязычного сообщества Ubuntu


Автор Тема: Bash. Работа с текстом. Поиск. Замена. Добавление в конец файла.  (Прочитано 2232 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Dark Smoke

  • Автор темы
  • Активист
  • *
  • Сообщений: 297
    • Просмотр профиля
    • Абонентское обслуживание и ремонт компьютеров в Днепропетровске
Добрый день
Сижу второй день над скриптом, не могу реализовать.

1. Есть файл с настройками key=>value
2. Мне дают новые настройки. Обычно это 4 - 5 новых настроек. Их надо добавить в файл.
3. если есть такие уже то заменяю значения
4. если нет, то добовляю в конец файла

Вот не как не получается на баше такое написать((

Например:

есть my.conf
param=test
url=my.domen.ru
json={'ddd':'222'}
Мне дали новые настройки которые мне надо добавить в файл my.conf
url=why.my.domen.ru
bat=true
То, ожидаемые действия:
1. url должен замениться на новое значение
2. bat добавиться в конец файла

Давать переменные хочу все сразу, например из другого файла.

Оффлайн ALiEN175

  • Старожил
  • *
  • Сообщений: 2204
  • X-9000SC
    • Просмотр профиля
comm --check-order -1 my.conf new.conf
Благодарности на Yandex 41001488642430. Cпасибо.

Оффлайн Dark Smoke

  • Автор темы
  • Активист
  • *
  • Сообщений: 297
    • Просмотр профиля
    • Абонентское обслуживание и ремонт компьютеров в Днепропетровске
comm --check-order -1 my.conf new.conf
comm - это что?
У меня в баше нет такой команды?

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 11894
  • Xubuntu 18.04 (64bit)
    • Просмотр профиля
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: http://help.ubuntu.ru/wiki/uefiboot

Оффлайн samson2

  • Участник
  • *
  • Сообщений: 169
    • Просмотр профиля
(Ubuntu 12.04),(Linux Mint 17.3),(Ubuntu Mate 16.04) .

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 11894
  • Xubuntu 18.04 (64bit)
    • Просмотр профиля
comm --check-order -1 my.conf new.conf
Кстати, у меня не сработало.
после сортировки файлов (что потребовал comm) мне эта команда выдала второй файл (сортированный)
$ comm --check-order -1 f0 f1
bat=true
url=why.my.domen.ru
без опции -1 дает:
$ comm --check-order f0 f1
bat=true
json={'ddd':'222'}
param=test
url=my.domen.ru
url=why.my.domen.ru
:-\

Совсем недавно решал подобную задачу в питоне - там через регулярные выражения решилось все достаточно красиво, но кода все равно довольно много вышло. Хотя конечно там чуточку иная задача была - и чисто такую можно довольно короким кодом обойтись.

В принципе по регулярке подменить значение можно через sed. Но для начала надо разделить второй файл на те что нужно обновлять и просто добавлять - как это сделать баше - я не скажу - просто не силен я в баше :(
« Последнее редактирование: 19 Январь 2016, 18:19:14 от Sly_tom_cat »
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: http://help.ubuntu.ru/wiki/uefiboot

Punko

  • Гость
Если через comm не выйдет, можно попробовать через grep.
Если ответ grep не пустой, то сначала удаляем исходную строку и вписываем новую.
Если ответ пустой, то просто вписываем.
Но костыль полнейший =)
Красивее искать sed`ом подстроку и заменять.

Оффлайн ALiEN175

  • Старожил
  • *
  • Сообщений: 2204
  • X-9000SC
    • Просмотр профиля
мда, поторопился я: comm тут не подойдет(
Благодарности на Yandex 41001488642430. Cпасибо.

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 11894
  • Xubuntu 18.04 (64bit)
    • Просмотр профиля
Если порядок следования переменных не важен, то можно красиво и довольно просто решить в питоне через словарь (dict), ну и конечно регулярка нужна для простого выделения ключа, хотя можно и через поиск '=' решить этот вопрос и простыми операциями над строками
Код: Python
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. import re, sys
  5.  
  6. with open(sys.argv[1], 'tr') as f:
  7.   org = dict([(re.findall(r'(.*)=', l)[0], l) for l in f])
  8. with open(sys.argv[2], 'tr') as f:
  9.   for l in f:
  10.     org[re.findall(r'(.*)=', l)[0]] = l
  11. for v in org.values():
  12.   print(v, end='')
  13.  

Записать код в файл (например: confjoin) и дать ему права на исполнеие (chmod -ax confjoin)
Вызывать confjoin <первый файл> <файл с обновлениями> (если confjoin не лежит в PATH то тогда к нему нужно полный путь указать для запуска)

ЗЫ Сортировка файлов не важна.
ЗЫЫ проверки входных параметров нет - т.е. если не то что-то задать - просто вывалится ошибкой.
« Последнее редактирование: 19 Январь 2016, 19:14:25 от Sly_tom_cat »
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: http://help.ubuntu.ru/wiki/uefiboot

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 11894
  • Xubuntu 18.04 (64bit)
    • Просмотр профиля
Вот нормальный интерфейс командной строки навесил:
Код: Python
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. import re, argparse
  5.  
  6. # Parse command line arguments
  7. parser = argparse.ArgumentParser(description='Joins original and update configuration files.')
  8. parser.add_argument('f0', metavar='orig_file', help='Path to original configuration file')
  9. parser.add_argument('f1', metavar='update_file', help='Path to file with new and updated configuration values')
  10. arg = parser.parse_args()
  11.  
  12. with open(arg.f0, 'tr') as f:
  13.   org = dict([(re.findall(r'(.*)=', l)[0], l) for l in f])
  14. with open(arg.f1, 'tr') as f:
  15.   for l in f:
  16.     org[re.findall(r'(.*)=', l)[0]] = l
  17. for v in org.values():
  18.   print(v, end='')

Тут и параметры потребует и usage напечатает (если параметров нужных не будет) и -h ключ вызова обработает.

$ ./confjoin -h
usage: confjoin.py [-h] orig_file update_file

Joins original and update configuration files.

optional arguments:
  -h, --help   show this help message and exit

Arguments:
  orig_file    Path to original configuration file
  update_file  Path to file with new and updated configuration values

... впринципе - вполне нормальная утилита получилась....
« Последнее редактирование: 19 Январь 2016, 20:10:56 от Sly_tom_cat »
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: http://help.ubuntu.ru/wiki/uefiboot

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5660
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Удобно на awk
Код: Bash
  1. awk '
  2.    BEGIN{FS=OFS="="}
  3.    {A[$1]=$2}
  4.    END{for(i in A)
  5.        print(i, A[i])>ARGV[1]}
  6.    ' my.conf new.conf
« Последнее редактирование: 19 Январь 2016, 20:12:50 от Azure »
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 11894
  • Xubuntu 18.04 (64bit)
    • Просмотр профиля
Azure, браво!  :D

Я вот белой завестью завидую людям которые одной строчкой баша реализую десяток строк питона или пару тысяч строк на С :)
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: http://help.ubuntu.ru/wiki/uefiboot

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5660
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Можно и sed
Код: Bash
  1. sed -zr ':;s/(\b[^\n=]+=)[^\n]+\n(.*\1)/\2/;t;w my.conf' <(cat my.conf new.conf)
« Последнее редактирование: 19 Январь 2016, 22:23:04 от Azure »
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 5660
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
Можно и grep'ом(но менее эффективно)
Код: Bash
  1. cat <(grep -o '^[^=]\+' new.conf | grep -wvFf - my.conf) new.conf
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Punko

  • Гость
Azure,
Это великолепно. Никак не могу осилить sed до такого уровня, а awk дфже трогать пока что боюсь.

 

Страница сгенерирована за 0.081 секунд. Запросов: 24.