Cat-файл для терминала на определенной скорости строк в секунду

15

Я ленивый, и я мог бы написать сценарий для этого, но я даже слишком ленив, чтобы думать о том, как это сделать.

Я часто делаю такие вещи, как:

cris$ python runexperiment.py > output.txt
cris$ cat output.txt

Иногда, когда я смотрю на длинный результат эксперимента, мне нравится позволять странице просто прокручивать и наблюдать, как формируются и рассеиваются последовательные шаблоны. Но использование cat для файла с 1 миллионом строк заканчивается за 5 секунд. Это слишком быстро даже для меня.

Есть ли способ, которым я могу замедлить скорость просмотра файла, что-то вроде «утилиты прокрутки»? Я хочу быстро, но не 200 тыс. Строк в секунду (все из которых, по-видимому, дисплей никогда не будет регистрироваться в любом случае).

Что-то вроде

cris$ scroll -lps=300 output.txt

И тогда я думаю, что сидеть сложа руки и смотреть, как проходит 300 строк в секунду, было бы идеально.

Крис Стрингфеллоу
источник
7
Попробуйте что-то вроде cat FILENAME | pv -l -L 900 -q. Ограничение в байтах в секунду, а не строк в секунду, поэтому я делаю этот комментарий, а не ответ.
Дэвид Шварц
Хорошо, это крутая утилита, которая работает частично. Но да, это немного изменчиво, так как идет после bps, а не lps.
Крис Стрингфеллоу

Ответы:

17

Коротко и читабельно :

perl -pe "system 'sleep .003'" log.txt

Я публикую эти решения, потому что они маленькие и удобочитаемые, так как комментарии к ответу DMas, кажется, способствуют решению такого рода!

Но я ненавижу это, потому что: для этого запуска perl разветвляется до /bin/sleep300x / секунд!

Это большой потребитель ресурсов! Также неправильно хорошие решения !

Использование встроенного сна в

К сожалению, встроенная функция sleepограничена целыми числами. Поэтому мы должны использовать selectвместо этого:

perl -e 'print && select undef,undef,undef,.00333 while <>;'

Под perl print while <>может быть заменен -pпереключатель:

perl -pe 'select undef,undef,undef,.00333'

Давай попробуем:

time /bin/ls -l /usr/bin | perl -pe 'select undef,undef,undef,.00333' | wc
   2667   24902  171131

real    0m9.173s
user    0m0.056s
sys     0m0.048s

bc -l < <(echo 2667/9.173)
290.74457647443584432573

Объяснение:

  • 300 строк / сек означает 1 строку на 0,0033333333 сек.

  • printбез аргумента печатает, $_что является полем ввода по умолчанию .

  • называется ... | perl -e, ... | perl -neили ... | perl -pe, стандартный ввод будет автоматически присвоен , *STDINкоторый дескриптор файла по умолчанию , так что <>будет делать то же самое, <STDIN>который будет считывать данные со стандартного ввода до тех пор $/( входной разделитель записей , который по умолчанию используется символ новой строки ) будет достигнута. На английском языке по умолчанию <>будет читать одну строку из стандартного ввода и назначать содержимое $_переменной.

  • &&это и состояние, но используется там в качестве командной цепи сепаратора так после (успешно) напечатать одну строку, делая следующую команду.

  • selectявляется трюк программиста не использоватьsleep . Эта команда предназначена для захвата событий в файловых дескрипторах (входные и / или выходные данные, файлы, сокеты и / или сетевые сокеты). С помощью этой команды программа может ожидать 3 вида событий, канал готов к чтению , канал готов к записи, и какое-то событие происходит в канале . Четвертый аргумент - это время ожидания в секундах, поэтому синтаксис таков select <feeds where wait for input>, <feeds where having to write>, <feed where something could happen>, <timeout>.

Для большей точности вы можете использовать Time::Hiresмодуль perl:

perl -MTime::HiRes -pe 'BEGIN{$start=Time::HiRes::time;$sleepPerLine=1/300};select undef,undef,undef,($start + $sleepPerLine*$. - Time::HiRes::time)'

Примечание: $.это номер текущей строки ввода .

Лучше написано как cat >catLps.pl

#!/usr/bin/perl -w

use strict;
use Time::HiRes qw|time|;

my $start=time;
my $lps=300;

$lps=shift @ARGV if @ARGV && $ARGV[0]=~/^(\d+)$/;
my $sleepPerLine=1/$lps;

print &&
    select undef,undef,undef,($start + $sleepPerLine*$. - Time::HiRes::time)
    while <>

Использование:

catLps.pl [lps] [file] [file]...

Первый аргумент lps- необязательная строка в секундах числового аргумента (по умолчанию: 300)

Примечание: если имя файла только числовые, вы , возможно , придется specifiy их с пути: ./3.

Как catэто может передавать файлы, заданные в качестве аргумента и / или стандартного ввода

Итак, мы могли бы:

TIMEFORMAT='%R' 
time seq 1 100 | ./catLps.pl 100 >/dev/null 
1.040

time seq 1 10000 | ./catLps.pl 10000 >/dev/null  
1.042

Ради забавы:

export TIMEFORMAT='%R' ;clear ;time seq 1 $((LINES-2)) | ./catLps.pl $((LINES-2))
Ф. Хаури
источник
2
это похоже на какого-то серьезного вуду, которого ты там делаешь. это так круто, я попробовал, и это работает. Я понятия не имею, как ты это сделал, хотя. какого черта Perl выбрать? UNDEF? я могу посмотреть это удивительный.
Крис Стрингфеллоу
2
@CrisStringfellow Хорошо, я добавил некоторые пояснения и полный сценарий с использованием Time::HiResмодуля Perl для большей точности
Ф. Хаури
мой Бог. Это потрясающий ответ. Спасибо. Я пытался поднять это во второй раз. Я учусь чему-то, читая ваше чудесное объяснение.
Крис Стрингфеллоу
2
Вы также можете высказать мои комментарии ;-)
Ф. Хаури
@CrisStringfellow Ответ отредактирован: с помощью команды -pswitch to perl скрипт был облегчен!
Ф. Хаури
11

просто используйте awk со сном:

awk '{print $0; system("sleep .1");}' log.txt
Dmas
источник
Это сработало для меня, и для моей ситуации это был лучший вариант, а не сценарий, описанный выше. Не уверен, почему за этот ответ проголосовали.
Гражданин Кеплер
2
В отличие от решения Perl, оно вполне читабельно.
Стрелок
1
@Gunslinger: Синтаксис system(*sleep .1")будет генерировать 10 форкс / сек! Это можно было бы написать perl -pe 'system "sleep .1"' log.txt: тоже читабельно, но очень дорого (не дружественно к системе!)
Ф. Хаури
Я тоже предпочитаю этот читаемый ответ. Единственное, он запускает команду сна для каждой строки, которую выводит. Но мне безразлично, насколько хорошо читается один вкладыш.
его
0

Я опаздываю на вечеринку, но я обнаружил, что это было бы полезным упражнением в обучении на python, поэтому я поделюсь тем, что получил

#!/usr/bin/env python3

import argparse
from time import sleep

parser = argparse.ArgumentParser(description='Echo a file slowly')
parser.add_argument('-i',
                    '--input-file',
                    type=argparse.FileType('r'),
                    default='-')
parser.add_argument('-d',
                    '--delay-in-ms',
                    type=int,
                    default='100')
args = parser.parse_args()

for line in args.input_file:
    print(line.rstrip())
    sleep(args.delay_in_ms/1000.0)

Он принимает ввод от stdin или в качестве аргумента (-i) и по умолчанию записывает одну строку в 1/10 секунды, но это можно изменить с помощью другого аргумента (-d).

Grezzo
источник
Благодарю. Я начал разрабатывать нечто похожее на эту идею в Python, когда натолкнулся на эту Q & Ad. Я отмечаю, что Python также поддерживает select docs.python.org/3/library/select.html аналогично Perl, как и в ответе Ф. Хаури.
ybull