Sed: однократная вставка в нужном месте

На самом деле это единственный раздел про unix на этом форуме

Модераторы: /dev/random, Модераторы разделов

vipermagi
Сообщения: 83
ОС: AgiliaLinux

Sed: однократная вставка в нужном месте

Сообщение vipermagi »

Имеется конфиг, примерно такой:

Код: Выделить всё

#
#разные каменты
и не только

#описание 1
option 1

#описание 2
option 2

#описание 3
option 3

#описание 4
option 4

другой конфигурационный
текст
#и другие каменты
#


Требуется однократно вставить дополнительную опцию после, или даже возможно перед, одной из существующих.

Мой вариант

Код: Выделить всё

sed -i '/option/,/^$/s/^$/вставляемый_текст/1' prog.conf

должен бы делать вставку в пустую строку после первой опции, но он вставляет и во все последующие.

А

Код: Выделить всё

sed -i '/option/,/^$/s/^$/вставляемый_текст/2' prog.conf

вообще не изменяет файл.

Что делать? Как быть?
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: Sed: однократная вставка в нужном месте

Сообщение allez »

vipermagi писал(а):
30.08.2009 11:53
Мой вариант

Код: Выделить всё

sed -i '/option/,/^$/s/^$/вставляемый_текст/1' prog.conf

должен бы делать вставку в пустую строку после первой опции, но он вставляет и во все последующие.

Этот вариант должен делать вставку после каждой строки, в которой есть слово "option". Если хотите делать вставку после первой опции, используйте "option 1", обеспечивая тем самым уникальность поискового выражения:

Код: Выделить всё

sed -i '/option 1/,/^$/s/^$/вставляемый_текст/1' prog.conf

Пример работы (командная строка несколько изменена)

$ sed '/option 1/,/^$/s/^$/вставляемый_текст\n/' prog.conf # #разные каменты и не только #описание 1 option 1 вставляемый_текст #описание 2 option 2 #описание 3 option 3 #описание 4 option 4 другой конфигурационный текст #и другие каменты #
Спасибо сказали:
vipermagi
Сообщения: 83
ОС: AgiliaLinux

Re: Sed: однократная вставка в нужном месте

Сообщение vipermagi »

Именно, что нужна не уникальность. А выбор из однообразия. Вот тут напипсано, что чтобы заменить только первое совпадение нужно писать s/// , чтобы заменить все совпадения нужно писать s///g, чтобы допустим третье, надо писать s///3. Меня интересуют четыре варианта замены: первое совпадение, последнее совпадение, >1 сначала и >1 сконца.
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: Sed: однократная вставка в нужном месте

Сообщение allez »

vipermagi писал(а):
30.08.2009 12:26
Вот тут напипсано, что чтобы заменить только первое совпадение...
Читайте внимательнее: в виду имеется первое совпадение только в текущей строке, а не во всем тексте.
Спасибо сказали:
vipermagi
Сообщения: 83
ОС: AgiliaLinux

Re: Sed: однократная вставка в нужном месте

Сообщение vipermagi »

allez писал(а):
30.08.2009 12:31
Производим обратную замену "?:%" на символы новой строки.


А на лету без создания промежуточных файлов можно? Хотя я не совсем понял что на что менять :)
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: Sed: однократная вставка в нужном месте

Сообщение allez »

Как вариант могу предложить такой порядок действий:
  • Заменяем в тексте символы новой строки на какое-нибудь сочетание символов (например, "?:%"). Получаем файл, в котором весь текст находится в одной строке.
  • Вставляем необходимый текст после нужного слова "option" - первого, третьего или пятнадцатого.
  • Производим обратную замену "?:%" на символы новой строки.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Sed: однократная вставка в нужном месте

Сообщение drBatty »

vipermagi писал(а):
30.08.2009 11:53
Требуется однократно вставить дополнительную опцию после, или даже возможно перед, одной из существующих.

Код: Выделить всё

'/option 1/ a\
insert text'

это вставляет ПОСЛЕ строки, ПЕРЕД - команда i, ВМЕСТО - c.
Команда s ищет совпадения и меняет их В ПРЕДЕЛАХ ОДНОЙ СТРОКИ.
vipermagi писал(а):
30.08.2009 11:53
Мой вариант
Код

Код: Выделить всё

sed -i '/option/,/^$/s/^$/вставляемый_текст/1' prog.conf

Эта строка работатет только в ДИАПАЗОНЕ, от /option/, до первло пустой строки включительно.
В этом диапазоне, она В КАЖДОЙ строке ищет пустую строку, и меняет её на "вставляемый_текст".
применение модификатора 1 - не имеет смысла - пустая строка может встретится только один раз в любой строке.


vipermagi писал(а):
30.08.2009 12:38
А на лету без создания промежуточных файлов можно? Хотя я не совсем понял что на что менять

можно вообще без файлов - уберите -i и имя, и набирайте в /dev/stdin, а читать - в /dev/stdout :)

allez писал(а):
30.08.2009 12:40
Как вариант могу предложить такой порядок действий:

1. Заменяем в тексте символы новой строки на какое-нибудь сочетание символов (например, "?:%"). Получаем файл, в котором весь текст находится в одной строке.

так делать НЕ следует - слишком много памяти пожрёт этот скрипт, и возможно завалит систему (во всяком случае сильно её затормозит).
хотя если вы УВЕРЕНЫ, что файлы мелкие (1-10000байт), то можно.

PS: кстати, можно и не заменять, а загрузить все строки текста в память командой N.
а потом ВСЕ строки сразу обработать. Но это хуже. Лучше и быстрее использовать адресные выражения.
Примеры можно посмотреть в info sed.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
vipermagi
Сообщения: 83
ОС: AgiliaLinux

Re: Sed: однократная вставка в нужном месте

Сообщение vipermagi »

Эх, а как всё оптимистически начиналось. Значит не столь всесильны grep/awk/sed. Жаль весьма.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Sed: однократная вставка в нужном месте

Сообщение drBatty »

vipermagi писал(а):
30.08.2009 15:58
Эх, а как всё оптимистически начиналось. Значит не столь всесильны grep/awk/sed. Жаль весьма.

почему-же?
вы просто неправильно их готовите.
sed обрабатывает текст построчно - желаете выбрать строки - есть адреса,
желаете внутри строки - есть s.
можете распилить строку, и юзать адреса внутри строки,
можете слить строки и юзать s в мультистрочном режиме.
все 4 варианта имеются. Где вы увидели ограничения "всесильности"?

ЗЫЖ 2 посл. варианта - обычно извращение. sed МОЖЕТ так делать, но лучше пользоваться обычным подходом.
Иногда, конечно, приходится извращаться... Если задача такая. У вас всё просто. Зачем тут это?
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: Sed: однократная вставка в нужном месте

Сообщение allez »

drBatty писал(а):
30.08.2009 13:42
так делать НЕ следует - слишком много памяти пожрёт этот скрипт, и возможно завалит систему (во всяком случае сильно её затормозит).
хотя если вы УВЕРЕНЫ, что файлы мелкие (1-10000байт), то можно.
Практика с теорией, как это нередко случается, чуток расходится... :)
Провел на своей рабочей машине эксперимент с файлами размером 74, 354 и 1770 мегабайт. Потребление памяти (общее) не превысило 180 мегабайт, процессор был загружен на 13%, тормозов не наблюдалось, система валиться не думала. :)

...

$ cat /proc/cpuinfo | grep "name" model name : Intel® Celeron® CPU 430 @ 1.80GHz $ ls -lh bdc.log -rw-r--r-- 1 user users 74M Авг 30 03:00 bdc.log $ free -m; time cat bdc.log | tr "n" "*&^" > /tmp/bdc.log; free -m total used free shared buffers cached Mem: 1510 1464 45 0 118 1187 -/+ buffers/cache: 158 1351 Swap: 1027 0 1027 real 0m0.635s user 0m0.116s sys 0m0.500s total used free shared buffers cached Mem: 1510 1466 44 0 118 1187 -/+ buffers/cache: 160 1350 Swap: 1027 0 1027 $ ls -lh http.log -rw-r----- 1 user users 354M Авг 30 18:53 http.log $ free -m; time cat http.log | tr "n" "*&^" > /tmp/http.log; free -m total used free shared buffers cached Mem: 1510 1477 32 0 118 1201 -/+ buffers/cache: 157 1353 Swap: 1027 0 1027 real 0m6.811s user 0m0.580s sys 0m2.476s total used free shared buffers cached Mem: 1510 1478 32 0 118 1201 -/+ buffers/cache: 157 1352 Swap: 1027 0 1027 # "Раздул" файл в 5 раз $ ls -lh http.log -rw-r--r-- 1 user users 1,8G Авг 30 20:15 http.log $ free -m; time cat http.log | tr "\n" "&^%" > /tmp/http.log; free -m total used free shared buffers cached Mem: 1510 1442 67 0 7 1268 -/+ buffers/cache: 167 1343 Swap: 1027 0 1027 real 1m0.400s user 0m2.764s sys 0m11.853s total used free shared buffers cached Mem: 1510 1479 31 0 7 1322 -/+ buffers/cache: 150 1360 Swap: 1027 0 1027


P. S. Провел тот же эксперимент на виртуальной машине с 256 мегабайтами ОЗУ над файлом размером 850 мегабайт. Файл обрабатывался 44 секунды, было занято 252 мегабайта ОЗУ и 88 килобайт свопа. Тормозов и нестабильностей опять-таки не наблюдалось, параллельно активно серфил Интернет в w3m. Общий вывод таков: при увеличении объема обрабатываемого файла приходится платить лишь временем. Надо отметить, что возрастание затрачиваемого времени примерно вдвое опережает "рост" файла, то есть при увеличении файла в 5 раз (с 354 до 1770 МБ) время обработки возрастает примерно в 10 раз (с 6,8 до 64 секунд).

Как-то вот так. :)
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Sed: однократная вставка в нужном месте

Сообщение drBatty »

allez писал(а):
30.08.2009 17:06
Практика с теорией, как это нередко случается, чуток расходится... :)

я про sed говорил.
и в случае 32Мб ОЗУ, и в случае 512Мб эффект один(конечно, файлы разные). К tr это не относится. Да и на sed ещё надо извратится такой скрипт написать (но я - смог).
И ещё: в info sed сказано, что GNU sed может многое (по части управления памяти), но вот nonGNU версии могут падать там, где ГНУтая нормально работает.

PS: да и зачем tr память? читает себе файл, и сразу пишет другой...
Вот для sed - да. она ещё строчку обрабатывает.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: Sed: однократная вставка в нужном месте

Сообщение allez »

drBatty писал(а):
31.08.2009 11:17
я про sed говорил.
А я - нет. Я определил задачу, но не называл инструмент. ;)

drBatty писал(а):
31.08.2009 11:17
PS: да и зачем tr память? читает себе файл, и сразу пишет другой...
Вот для sed - да. она ещё строчку обрабатывает.

Замена одних символов другими, которую производит tr, обработкой уже не считается... :)

Впрочем, не будем спорить. Вы стремитесь если не все, то почти все делать sed-ом - пусть будет так, это целиком и полностью ваше право и я ни в коем случае его не оспариваю и на него не посягаю. Я же предпочитаю использовать для решения задачи тот инструмент, который, на мой взгляд, справляется с ней наиболее эффективно. Разумеется, с поправкой на пробелы в моих познаниях, а также мою лень и пофигизм. :)
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: Sed: однократная вставка в нужном месте

Сообщение allez »

vipermagi писал(а):
30.08.2009 12:38
А на лету без создания промежуточных файлов можно?
Совсем без них обойтись, пожалуй, не удастся. Можно попытаться сделать что-то вроде этого:

Код: Выделить всё

cat prog.conf | tr "\n" "@#%" | sed 's/option [0-9]\{1,\}/&\nвставляемый_текст\n/1' | tr "@#%" "\n" > tmpfile; mv tmpfile prog.conf

Но, как совершенно справедливо заметил drBatty, нужно быть очень осторожным с подобного рода конструкциями, иначе есть шанс столкнуться с переполнением стека, ограничением на длину строки (в не GNU-версиях sed) и т. д. Впрочем, я и в этом случае не пренебрег ходовыми испытаниями: файл размером в 1414 мегабайт без проблем был обработан этой командной за 14 секунд на моей рабочей машине (объем ОЗУ - 1,5 ГБ). При этом sed занял около 950 МБ ОЗУ, но память не была исчерпана полностью. Замедления отклика системы не наблюдалось.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Sed: однократная вставка в нужном месте

Сообщение drBatty »

allez писал(а):
31.08.2009 12:27
Замена одних символов другими, которую производит tr, обработкой уже не считается... :)

Нет конечно!
Не считается обработкой СТРОКИ, потому ВСЮ строку tr может не хранить.
Кстати, большие строки бывают очень редко - в большинстве больших файлов(avi, tbz, mp3...) информация сжата, и потому, в среднем длинна строки равна 256 байт, причёю имеет место нормальное распределение длинны, т.о. вероятность строки длинной 25600 крайне мала, а это - не сложно для sed.

Тем не менее, у меня есть файлы, со строками в десятки Мб - это дампы MySQL. Вот с ними sed загибается(tr - нет).

allez писал(а):
31.08.2009 13:17
Впрочем, я и в этом случае не пренебрег ходовыми испытаниями:

попробуйе собрать все строки в одну, например:

Код: Выделить всё

sed -n 'H;${x;s/\n/~/gp}' test_file


allez писал(а):
31.08.2009 13:17
(объем ОЗУ - 1,5 ГБ). При этом sed занял около 950 МБ ОЗУ, но память не была исчерпана полностью. Замедления отклика системы не наблюдалось.

ага... а что-бы было с моей машинкой, где всего 512Мб?
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: Sed: однократная вставка в нужном месте

Сообщение allez »

drBatty писал(а):
31.08.2009 21:53
Не считается обработкой СТРОКИ, потому ВСЮ строку tr может не хранить.
Уточните, пожалуйста, что вы подразумеваете под обработкой строки, чтобы мы могли прийти к некоторому общему знаменателю. :)
Например, если команда tr "foo" "bar" обработкой строки не занимается, то команда sed 's/foo/bar/g' тоже строку не обрабатывает? Или я что-то не так понял?

drBatty писал(а):
31.08.2009 21:53
ага... а что-бы было с моей машинкой, где всего 512Мб?
Это да, в таком случае sed наверняка выдаст что-то вроде "couldn't reallocate memory", тут вы опять целиком и полностью правы.
Спасибо сказали: