LINUX.ORG.RU

sed в цикле.


0

1

Может кто подскажет, третий день бьюсь.

Есть файл


AAAABBBBCCC DDDD TTTTT
SSSSAAAABBBBBTTTTTAAAAA
QQQQQ
RRRRR
RRRRR
YYYYY

GGGGGGTTTTTOOOOOLLLLLL
SRRRRRRGGGGG
RRRRR
RRRRR
RRRRR
RRRRR
TTTTT

AAAABBBBBCCCCCDDDDTTTTT
SSSSBBBBAAAAATTTTTAAAAAA
TTTTT

Файл - большой текстовый файл разбитый на блоки. Разделитель между блоками - пробел. Задача: поменять в каждом блоке во второй строке pattern1 на pattern2. В примере пусть это будет TTTTT на 11111. Проблемы: - величина каждого блока может быть разной и pattern1 может вообще отсутствовать. - pattern1 в других строках должен остаться без изменений. Может еще какие-то вопросы по условию не осветил.

Вот что накалякал я.

#!/bin/bash
for i in $(cat test1 | sed -n '/^$/ =')
#Получаем список i. Где i - номер пустой строки.

do i=$[$i+2]
#делаем смещение на 2 строки вниз

echo $i >>tests
#для удобства сохряняю номера всех строк, где должен быть pattern1, хотя его может и не быть.

#cat test1 | sed -e «„${i}“ s/TTTTT/1111/»
#1-й вариант - в каждой строке с номером i провести замену. Команда выполняется столько раз, сколько пустых строк есть в файле. При этом вывод результатов - это повторение исходного файла * на количество пустых строк, что неприемлемо.

cat test1 | sed -e «„${i}“ s/TTTTT/1111/w test1»
#2-й вариант По идее делает тоже самое, что и в первом случае, но результат обработки каждого i должен накладываться на уже существующий. То есть произошла замена - измененный файл заменил оригинал. Реально виден только результат обработки первого i. И к тому же вообще не понятно почему в конце файла вставляется вся измененная строка.

#cat test1 | sed -e «„${i}“ s/TTTTT/11111/» >test1
#3-й вариант, как я понимаю - аналог 2-го. То есть результат обработки i должен записываться в исходный файл. А действительности файл test1 получается пустой.

done

Мои чайниковские мозги подсказывают, что, вероятно, проблема с открытием и закрытием файла test1. Но как через баш заставлять закрываться измененный файл test1? Или есть другие, более пододящие для таких целей инструменты, кроме sed?

Заранее спасибо!

Тут структура над строками => `sam' плохо подходит, можно `sam':

xsel -o | ssam ',x/(.+\n)+/ x/^.*\n.*/ x/\n.*/ {
s/TTTTT/11111
}'

Хотя проще `awk': создаем счетчик строки внутри блока, обнуляем при пустой строке, когда он =2 заменяем.

Смеха ради:

eddie -mData.List.{Split,Utils} 'unlines .  map (unlines . (\(x:y:zs) -> x:replace "TTTTT" "11111" y:zs) . lines) . splitOn "\n\n"'
n01r ★★
()
Ответ на: комментарий от anonymous

Вообщем если перед первым блоком тоже есть пустая строка, то можно так:

for i in $(egrep -n '^$' file | cut -f 1 -d ':'); do let i+=2; sed -i "${i}s/TTTT/1111/" file; done

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от n01r

чо за sam?

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

anonymous
()
Ответ на: комментарий от anonymous

Ну этот из plan9ports, хотя можно ограничиться бинарем (и двумя скриптами к нему).

уёбищных регулярок

По-моему вполне читабельно, выделяем: блок непустых строк -> две первые строки -> вторую сроку.

В любом случае, смесь bash+grep+cut+sed не comme if faut, тот же `awk':

awk '{i++}; i==2 {sub(«TTTTT»,«11111»)}; 1; /^$/ {i=0}'

n01r ★★
()
Ответ на: комментарий от n01r

вполне, но если ТС не осилил решить такую задачу за три дня…

anonymous
()
Ответ на: Спасибо! от Gr0mazeka

А я топик невнимательно читал и сделал совсем не то :)

Xenesz ★★★★
()
Ответ на: Спасибо! от Gr0mazeka

только вот, как ниже извенился товарищ, эта команда заменит каждое первое вхождение в каждой строке pattern1 на pattern2

anonymous
()
Ответ на: комментарий от anonymous

Это не важно. Меня надо было ткнуть в -i. Обидно, что в мане и в инфо читал ВСЕ.... кроме того, что надо :(

Спасибо и за пример на awk, буду разбираться в его работе.. Потому как 40 минут на 6М файлик - многовато.

Gr0mazeka
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.