Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Unix-системы Новый топик    Ответить
 Циклический буфер средствами bash  [new]
Alibek B.
Member

Откуда:
Сообщений: 3313
Скрипт при каждом запуске добавляет строку в текстовый файл.
Мне нужно сделать так, чтобы в этом файле всегда было 15 последний строк.
То есть после добавления новой строки нужно удалить все устаревшие строки.
И желательно без вспомогательного файла (то есть скопировать в новый файл 15 последних строк, удалить старый файл, переименовать новый файл в старый).
tail -n 15 file > file не работает, файл получается пустой (потому что открыт в конвейере)
Самое компактное и простое, что у меня получилось, это такое: tail -n 15 file | tee file > /dev/null
Есть что-нибудь лучше?
29 окт 19, 13:27    [22004989]     Ответить | Цитировать Сообщить модератору
 Re: Циклический буфер средствами bash  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 18211
В Linux sed умеет править "по месту"
30 окт 19, 01:59    [22005631]     Ответить | Цитировать Сообщить модератору
 Re: Циклический буфер средствами bash  [new]
CrazyMihey
Member

Откуда: Россия, Москва
Сообщений: 504
Это можно реализовать Средствами Потокового Текстового Редактора SEd, если присутствует Уверенность в том, что Задачу нужно Решать именно в эту Сторону:
 File=~/Test.Txt	# Имя Обрабатываемого Файла.
 Lins="15"	# Количество Последних Скрок, которые должны остаться в Файле.
 for i in $(seq 128); do printf "Это Строка № %3u\n" "${i}" >> ${File}; done	# Создаём Большой Текстовый Файл, состоящий из 128 Строк.
 sed -e "$(("$(sed -n -e "$=" "${File}")" + 1 - "${Lins}")),\$$(printf "!")d" -i "" "${File}"	# Собственно, Удаление Лишних Строк.
 cat "${File}"
Это Строка № 114
Это Строка № 115
Это Строка № 116
Это Строка № 117
Это Строка № 118
Это Строка № 119
Это Строка № 120
Это Строка № 121
Это Строка № 122
Это Строка № 123
Это Строка № 124
Это Строка № 125
Это Строка № 126
Это Строка № 127
Это Строка № 128
 rm "${File}"
РазЯснения:
"$(sed -n -e "$=" "${File}")"" — Общее Количество Строк в Файле.
$(("$(sed -n -e "$=" "${File}")" + 1 − "${Lins}")) — Номер Первой Строки, которая должна СоХраниться. «+ 1» — Это потому что Нумерация Строк идёт с Единицы.
Выражение в SEd «<Число>,$» означает Обработку Строк от <Число> и до Конца Файла. Символ Конца Файла «$» экранируется Обратным Слэшом «\» только потому, что после Него снова идёт Символ «$», относящийся к Следующей Конструкции «$(…)» (Выполнение ПодКоманды).
Конструкция «$((…))» — ЦелоЧисленная Арифметика в SH/BASH.
Конструкция «$(printf "!")d» используется исключительно для того, чтобы BASH не охуел при виде «!» в Командной Строке. Если использовать внутри Скрипта, то можно заменить на просто «!d», что означает «Не Удалять Строки».
Параметр «-i ""» предписывает Редактору SEd изменить Существующий Файл и не создавать при Этом Резервную Копию.
Если Что-то НеПонятно: «man sh, man bash, man sed, man …»
5 ноя 19, 18:01    [22010162]     Ответить | Цитировать Сообщить модератору
 Re: Циклический буфер средствами bash  [new]
mayton
Member

Откуда: loopback
Сообщений: 42902
Alibek B.
Скрипт при каждом запуске добавляет строку в текстовый файл.
Мне нужно сделать так, чтобы в этом файле всегда было 15 последний строк.
То есть после добавления новой строки нужно удалить все устаревшие строки.
И желательно без вспомогательного файла (то есть скопировать в новый файл 15 последних строк, удалить старый файл, переименовать новый файл в старый).
tail -n 15 file > file не работает, файл получается пустой (потому что открыт в конвейере)
Самое компактное и простое, что у меня получилось, это такое: tail -n 15 file | tee file > /dev/null
Есть что-нибудь лучше?

Варианты.

Можно держать 15 файлов и переименовывать. Типа.

rm last15row.txt
mv last14row.txt last15row.txt
mv last13row.txt last14row.txt
..............
mv last1row.txt last2row.txt


При каждом добавлении строки та логика которая добавляет должна просто создавать файл last1row.txt

Еще думаю тоже самое можно сделать на сим-линках. В этом случае можно файлы вообще не удалять
а хранить целую историю. +Будет скользящее окно из линков которые будут отображаться на полседние 15 строк.
Алгоритм - по сути тот-же самый. Вместо mv будет cp -s
6 ноя 19, 20:54    [22011093]     Ответить | Цитировать Сообщить модератору
 Re: Циклический буфер средствами bash  [new]
volodin661
Member

Откуда: Внутренняя Монголия
Сообщений: 445
Дорогой ты наш человек,

да просто берёшь VIM версию 8 ( не ниже ), тренируешься в нём, осуществляя все необходимые тебе редактирующие действия,
а потом автоматизируешь из ком. строки с помощью ключа --remote-send

vim --servername VIM --remote-send ':$ append<CR>XXXXXXX<CR><C-\><C-N>:2,16 move 0<CR>:16 delete<CR>'


где:
XXXXXXXXXXX - добавляемая в конец буфера строка
<CR> - синтаксис перевода строки
<C-\><C-N> - синтаксис переключения в нормальный режим из любого режима
8 ноя 19, 07:40    [22012030]     Ответить | Цитировать Сообщить модератору
 Re: Циклический буфер средствами bash  [new]
volodin661
Member

Откуда: Внутренняя Монголия
Сообщений: 445
PS: Ну и в конце добавляй 'write<CR>', конечно, если тебе вдруг надо из этого файла читать содержимое какой-нибудь утилитой.
8 ноя 19, 07:49    [22012033]     Ответить | Цитировать Сообщить модератору
 Re: Циклический буфер средствами bash  [new]
volodin661
Member

Откуда: Внутренняя Монголия
Сообщений: 445
A perl чем не угодил ?

writebuf:
#!/usr/bin/env perl
use Tie::File;

tie   @array, 'Tie::File', test15 or die $!;
push  @array, shift;
shift @array while  $#array > 14; 
untie @array; 


chmod +x writebuf


./writebuf "Графиня изменившимся лицом бежит пруду"
8 ноя 19, 08:11    [22012038]     Ответить | Цитировать Сообщить модератору
 Re: Циклический буфер средствами bash  [new]
volodin661
Member

Откуда: Внутренняя Монголия
Сообщений: 445
PS: запись идёт в файл test15
8 ноя 19, 08:15    [22012039]     Ответить | Цитировать Сообщить модератору
 Re: Циклический буфер средствами bash  [new]
volodin661
Member

Откуда: Внутренняя Монголия
Сообщений: 445
perl -MTie::File -E 'tie@a,"Tie::File","test15"||die$!;push@a,shift;shift@a while$#a>14;untie@a' "Графиня бежит"
8 ноя 19, 08:28    [22012046]     Ответить | Цитировать Сообщить модератору
 Re: Циклический буфер средствами bash  [new]
Alibek B.
Member

Откуда:
Сообщений: 3313
В конечном итоге сделал через tail -n 15 file > new и последующим mv -f new file.
Способ с использованием tee оказался нестабильным, а все прочие вариации редактирования исходного файла (через sed или vi) по результатам strace/time менее эффективны.
8 ноя 19, 08:28    [22012047]     Ответить | Цитировать Сообщить модератору
 Re: Циклический буфер средствами bash  [new]
volodin661
Member

Откуда: Внутренняя Монголия
Сообщений: 445
Alibek B.
результатам strace/time менее эффективны.


Если приоритет на эффективность, то просто написать 8 строчек на "C".
8 ноя 19, 08:31    [22012053]     Ответить | Цитировать Сообщить модератору
 Re: Циклический буфер средствами bash  [new]
Alibek B.
Member

Откуда:
Сообщений: 3313
Эффективность с использованием существующих инструментов.
tail есть везде, а C не знаю.
8 ноя 19, 08:41    [22012055]     Ответить | Цитировать Сообщить модератору
Все форумы / Unix-системы Ответить