LINUX.ORG.RU

Замена блока текста между маркерами

 , ,


0

1

Есть файл

...
aaa
...
rem
...
bbb
...

Надо заменить блок между aaa и bbb на ccc.

...
aaa
ccc
bbb
...

С ходу нагуглилось решение на awk:

cat $TESTF | awk '
$0 == "aaa" {skip=1; next;}
$0 == "bbb" {skip=0; print "ccc"}
!skip {print}
'

но не заработало. На чем решать все равно, лишь бы было чуть быстрее черепахи

★★

Последнее исправление: sambist (всего исправлений: 1)

Ответ на: комментарий от beastie

А в чем кривость-косость проявляется?

sambist ★★
() автор топика
while (...) {
	$_ = "ccc\n" if /aaa/ .. /bbb/ and not m/aaa|bbb/;
	print;
}
joy4eg ★★★★★
()
Ответ на: комментарий от thriller

Все работает, но можно как-то это модифицировать, чтобы оно учитывало количество пробелов, которое было перед aaa изначально и добавляло их к каждой строке в замене?

Поясняю:

было:

    aaa
    rem
    bbb

стало

aaa
ccc
bbb

надо:

    aaa
    ccc
    bbb

Мелочь, но неприятно.

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

Проще или единственный путь? Просто чтобы ассоциативный массив в awk передать это надо его в одну строку собирать снаружи, а потом расфасовывать внутри.

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

ассоциативный массив в awk передать

А это вам зачем? И как вы собираетесь использовать его в sed при условии, что в нём никаких массивов нет? (Там вообще кроме pattern space и hold space ничего нет.) У меня, конечно, есть некоторые подозрения, зачем, но тогда моим ответом на это будет «perl/python/ruby по вкусу»; примитивный перловый вариант, кстати, в треде уже есть.

thriller ★★
()
Последнее исправление: thriller (всего исправлений: 1)
Ответ на: комментарий от thriller

И тут я вспомнил, что в pattern space можно засунуть весь вход. В итоге задача сводится к простой (хе-хе) регулярке:

echo -e '  aaa\nddd\nddd\n  bbb' | sed -re ':x; N; $!b x; s/(^|\n)(\s*)(aaa)\n(.*?)\n\2(bbb)(\n|$)/\1\2\3\n\2ccc\n\2\5\6/g'
  aaa
  ccc
  bbb

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

А можно их услышать?

Я, например, подумал про массив, отображающий aaa-паттерны в ccc. Но, с другой стороны, какая вам-то разница до моих предположений? Задача ведь ваша, не моя ☺

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

Я, например, подумал про массив, отображающий aaa-паттерны в ccc.

На самом деле у меня есть ассоциативный массив, часть aaa - ключ, внутрь вставляется value.

Но, с другой стороны, какая вам-то разница до моих предположений?

Ну интересно, что про меня люди думают. 😋

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

Тут маленькая проблемка: ваш пример с aa-bbb-ccc работает, а при моей попытке засандалить туда переменную говорит «бе»:

sed -ire ":x; N; $!b x; s@(^|\n)(\s*)(${START})\n(.*?)\n\2(${STOPSEQREG})(\n|$)@\1\2\3\n\2${ENUMARRAY[$i]}\n\2\5\6@g" $f

sed: -e выражение #1, символ 210: Неверная ссылка назад
sed: -e выражение #1, символ 164: Неверная ссылка назад
sed: -e выражение #1, символ 195: Неверная ссылка назад

Я так понимаю, что он так реагирует на какой-то символ внутри переменных. / пришлось заменить на @, ибо внутри переменных есть /, \, *, + и -

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

Блин, короче такая ситуация: посидел почесал репу. Добился того, что нормально подстанавливаются переменные. Но есть косяк.

echo -e '  aaa\nddd\nddd\n  bbb\n  aaa\nddd\nddd\n  bbb' | sed -re ':x; N; $!b x; s/(^|\n)(\s*)(aaa)\n(.*?)\n\2(bbb)(\n|$)/\1\2\3\n\2ccc\n\2\5\6/g'

Попробуйте.

Товарищ thriller, на седе так получается нельзя сделать, да?

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