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


Получить помощь и пообщаться с другими пользователями Ubuntu можно
на irc канале #ubuntu-ru в сети Freenode
и в Jabber конференции ubuntu@conference.jabber.ru

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

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

Оффлайн Dark Smoke

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

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 добавиться в конец файла

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

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6755
  • 20% Cooler
    • Просмотр профиля
comm --check-order -1 my.conf new.conf
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

Оффлайн Dark Smoke

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

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12130
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: https://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!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12130
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
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 - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

Punko

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

Оффлайн ALiEN

  • Администратор
  • Старожил
  • *
  • Сообщений: 6755
  • 20% Cooler
    • Просмотр профиля
мда, поторопился я: comm тут не подойдет(
🖥 AsRock B550M Pro4 :: AMD Ryzen 5 3600 :: 16 GB DDR4 :: AMD Radeon RX 6600 :: XFCE
💻 ACER 5750G :: Intel Core i5-2450M :: 6 GB DDR3 :: GeForce GT 630M :: XFCE

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12130
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Если порядок следования переменных не важен, то можно красиво и довольно просто решить в питоне через словарь (dict), ну и конечно регулярка нужна для простого выделения ключа, хотя можно и через поиск '=' решить этот вопрос и простыми операциями над строками
Код: (python) [Выделить]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import re, sys

with open(sys.argv[1], 'tr') as f:
  org = dict([(re.findall(r'(.*)=', l)[0], l) for l in f])
with open(sys.argv[2], 'tr') as f:
  for l in f:
    org[re.findall(r'(.*)=', l)[0]] = l
for v in org.values():
  print(v, end='')

Записать код в файл (например: 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 - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12130
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Вот нормальный интерфейс командной строки навесил:
Код: (python) [Выделить]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import re, argparse

# Parse command line arguments
parser = argparse.ArgumentParser(description='Joins original and update configuration files.')
parser.add_argument('f0', metavar='orig_file', help='Path to original configuration file')
parser.add_argument('f1', metavar='update_file', help='Path to file with new and updated configuration values')
arg = parser.parse_args()

with open(arg.f0, 'tr') as f:
  org = dict([(re.findall(r'(.*)=', l)[0], l) for l in f])
with open(arg.f1, 'tr') as f:
  for l in f:
    org[re.findall(r'(.*)=', l)[0]] = l
for v in org.values():
  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 - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

Оффлайн Azure

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

Оффлайн Sly_tom_cat

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

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

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 6017
  • Windows10, i3wm on Debian9, Manjaro20.0
    • Просмотр профиля
Можно и sed
Код: (bash) [Выделить]
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

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

Punko

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

 

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