URL: https://www.opennet.ru/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 8135
[ Назад ]

Исходное сообщение
"Требуются помощь по SED. Два файла."

Отправлено bzmn , 08-Мрт-09 13:58 
помогите, пожалуйста. очень трудно даются маны :(

есть file1. нужно:

удалить все строки, ПОСЛЕ строки, содержащей metka_begin
ПОКА не встретиться строка, содержащая metka_end

строки, содержащие metka_begin и metka_end трогать не нужно. их оставить. _только между ними_ удалить.

маленькая оговорка: строка, содержащая metka_end встречается неоднократно, а содержащая metka_begin - только один раз. но удалить нужно между строками С metka_begin ПО ближайший metka_end.

после чего, в ту же область в тот же file1 вставить всё содержимое другого файла (file2)


Содержание

Сообщения в этом обсуждении
"Требуются помощь по SED. Два файла."
Отправлено angra , 08-Мрт-09 14:15 
Какая религия заставляет вас использовать для этой задачи именно sed?



"Требуются помощь по SED. Два файла."
Отправлено bzmn , 08-Мрт-09 14:35 
>Какая религия заставляет вас использовать для этой задачи именно sed?

наверное, религия Майкрософта, ибо я не использую ЮНИКС-системы, просто решил, что здесь есть знатоки по SED, которые могут помочь в этом вопросе (синтаксис у SED под Win/NIX все равно ведь похожий - главное, алогоритм, а тама разберусь). Другой _консольной_ программы под Windows, которая гипотетически могла бы справиться с этой задачей, я просто не знаю.

если SED не может удалить строки по заданному мною параметру, то может он хотя бы вставить всё содержимое file2 в file1 ПОСЛЕ строки, содержащей metka_begin? А те старые я могу извратом убить через s//g.

Если у вас будут рекомендации - буду очень благодарен.


"Требуются помощь по SED. Два файла."
Отправлено angra , 08-Мрт-09 16:34 
Мне кажется как раз вставка из другого файла будет основной проблемой, а вот удаление строк по указанным критериям вполне возможно в sed. Специалисты по sed на этом форуме есть, остается их дождаться :)
Мне лично лень учить синтаксис sed/awk/grep/итд, особенно с учетом их вариаций, значительно проще выучить Perl и использовать его как swiss army knife. Кстати perl под винду есть, мне известно аж три варианта - cygwin, active perl, strawberry perl - плюс в денвере вроде есть свой минимальный вариант.
Если заинтересует, то однострочник на perl:
perl -ne 'BEGIN{local $/=undef;open F,"file2";$t=<F>;close F};print unless $f;$f=1 if /metka_begin/;if (/metka_end/ & $f){print $t,$_;$f=0};' file1
Экранирование дано для bash, так что для cmd нужно будет модифицировать. Выводит на stdout, но если добавить -i, то будет менять внутри файла. Можно давать много файлов за раз.

"Требуются помощь по SED. Два файла."
Отправлено bzmn , 08-Мрт-09 17:10 
>[оверквотинг удален]
>Мне лично лень учить синтаксис sed/awk/grep/итд, особенно с учетом их вариаций, значительно
>проще выучить Perl и использовать его как swiss army knife. Кстати
>perl под винду есть, мне известно аж три варианта - cygwin,
>active perl, strawberry perl - плюс в денвере вроде есть свой
>минимальный вариант.
>Если заинтересует, то однострочник на perl:
>perl -ne 'BEGIN{local $/=undef;open F,"file2";$t=<F>;close F};print unless $f;$f=1 if /metka_begin/;if (/metka_end/ & $f){print $t,$_;$f=0};' file1
>Экранирование дано для bash, так что для cmd нужно будет модифицировать. Выводит
>на stdout, но если добавить -i, то будет менять внутри файла.
>Можно давать много файлов за раз.

Друг! Спасибо тебе. Попробовал денверский на 700 кб - результат удовлетворительный (пока, правда, на тестовых файлах, но, думаю, и на рабочих будет). Из синтаксиса только ' заменил на ".

Спасибо, спасибо!


"Требуются помощь по SED. Два файла."
Отправлено angra , 08-Мрт-09 17:59 
На всякий случай добавлю пару моментов.
Если вопреки условиям задачи встретится еще раз пара metka_begin/metka_end, то для нее тоже будет произведена замена на содержимое file2.
Если metka_end не встретится вообще, то удаление строк будет до конца файла и вставки из file2 не будет.



"Требуются помощь по SED. Два файла."
Отправлено bzmn , 08-Мрт-09 18:11 
>На всякий случай добавлю пару моментов.
>Если вопреки условиям задачи встретится еще раз пара metka_begin/metka_end, то для нее
>тоже будет произведена замена на содержимое file2.
>Если metka_end не встретится вообще, то удаление строк будет до конца файла
>и вставки из file2 не будет.

пара не встретится. metka_begin только один. metka_end - много. но ОТ/ДО - пара, получается, одна. но за уточнения, безусловно, спасибо.

тут щас была маленькая загвоздка. metka_end и metka_begin - условные ведь обозначения были.

на самом деле, там так:

<list name="IpAccessList"> - metka_begin. В качестве нее скормил IpAccessList
</list> - metka_end. Возникла маленькая загвоздка, ибо не мог скормить просто list, потому что в удаляемом содержимом встречается </listitem>. Попытался скормить полностью </list> - перл заругался на синтаксис. Но когда отдал ему list> - вроде, проканало.

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

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


"Требуются помощь по SED. Два файла."
Отправлено angra , 08-Мрт-09 18:45 
Как будет время советую почитать "Mastering regular expressions" http://oreilly.com/catalog/9781565922570/. Можно найти в сети, говорят даже не русском. Умение работать с регулярными выражениями очень сильно помогает админу и программисту, фактически must have.
Однако в данном случае проблема была в синтаксисе самого оператора m//, как можно заметить / ограничивает регулярное выражение, но также встречается в </list>. Решить можно либо экранированием: /<\/list>/(возможно понадобится еще учитывать экранирование от самого cmd и тогда получим /<\\/list>/) либо заменой / на другой символ с явным указанием оператора m, например m|</list>| или m#</list>#. Второй способ удобней если слешей много.



"Требуются помощь по SED. Два файла."
Отправлено gaa , 08-Мрт-09 21:43 
> <list name="IpAccessList"> - metka_begin. В качестве нее скормил IpAccessList
> </list> - metka_end

То есть тебе надо обрабатывать XML? Тогда выкидывай и перл и сед, потому что они с ним в общем случае не справляются.
Лучше либо парсить XML напрямую, либо использовать http://sourceforge.net/projects/xmlstar/ .


"Требуются помощь по SED. Два файла."
Отправлено bzmn , 08-Мрт-09 22:51 
>> <list name="IpAccessList"> - metka_begin. В качестве нее скормил IpAccessList
>> </list> - metka_end
>
>То есть тебе надо обрабатывать XML? Тогда выкидывай и перл и сед,
>потому что они с ним в общем случае не справляются.
>Лучше либо парсить XML напрямую, либо использовать http://sourceforge.net/projects/xmlstar/ .

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


"Требуются помощь по SED. Два файла."
Отправлено ASN , 08-Мрт-09 21:46 
>[оверквотинг удален]
>
>строки, содержащие metka_begin и metka_end трогать не нужно. их оставить. _только между
>ними_ удалить.
>
>маленькая оговорка: строка, содержащая metka_end встречается неоднократно, а содержащая metka_begin - только
>один раз. но удалить нужно между строками С metka_begin ПО ближайший
>metka_end.
>
>после чего, в ту же область в тот же file1 вставить всё
>содержимое другого файла (file2)

$ cat script.sed
/metka_begin/,/metka_end/{
  /metka_begin/{
    r file2
    b
  }
  /metka_end/b
  d
}

$ sed -f script.sed file1


"Требуются помощь по SED. Два файла."
Отправлено bzmn , 08-Мрт-09 22:48 
>[оверквотинг удален]
>/metka_begin/,/metka_end/{
>  /metka_begin/{
>    r file2
>    b
>  }
>  /metka_end/b
>  d
>}
>
>$ sed -f script.sed file1

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