Добавляя в начало каждой строки, сколько времени потребовалось для ее генерации

После строки

my @titlewords = split /\s+/, $title;    #/ get words

добавьте код для удаления слов из массива:

my @new;
foreach my $t (@titlewords){
    push(@new, $t) if $t !~ /^(and|if|the)$/i;
}
@titlewords = @new;
3
09.09.2017, 09:10
5 ответов

Предположим, что сценарий, генерирующий выходные данные, называется generate. Затем, чтобы отобразить количество секунд, необходимое для создания каждой строки:

$ generate | ( t0=$(date +%s); while read -r line; do t1=$(date +%s); echo " $((t1-t0)) $line"; t0=$t1; done )
 2 foo
 0 foo
 5 foo
 3 foo

Одни и те же команды, разбросанные по нескольким строкам, выглядят так:

generate | ( t0=$(date +%s)
    while read -r line
    do
        t1=$(date +%s)
        echo " $((t1-t0)) $line"
        t0=$t1
    done
    )

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

timer() { t0=$(date +%s); while read -r line; do t1=$(date +%s); echo " $((t1-t0)) $line"; t0=$t1; done; }

Мы можем использовать эту функцию следующим образом:

$ generate | timer
 0 foo
 2 foo
 4 foo
 3 foo

Как это работает

  • t0=$(date +%s)

    Это фиксирует текущее время в начале сценария в секундах -с эпохи -.

  • while read -r line; do

    Это запускает цикл, который читает со стандартного ввода

  • t1=$(date +%s)

    Это фиксирует время в секундах -с -эпохи, в которую была захвачена текущая строка.

  • echo " $((t1-t0)) $line"

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

  • t0=$t1

    Это обновляет t0для следующей строки.

  • done

    Это сигнализирует об окончании цикла while.

5
27.01.2020, 21:08

Вы можете использоватьtime(примечание :отдельный двоичный файл, а не оболочку, встроенную -в ), и комбинировать ее с циклом while. Чтобы получить время выполнения для каждой команды:

while read -r line; do
    /usr/bin/time -f "%e %C" $line 2>&1
done

Пример вывода:

0.1 sleep 0.1
0.2 sleep 0.2
1.0 sleep 1

Если вы хотите получить общее время выполнения с самого начала, вам необходимо просуммировать время выполнения для каждого шага. Точность для формата %eсоставляет 1/100 секунды, поэтому вы не можете использовать целочисленную арифметику оболочки напрямую (в зависимости от используемой вами оболочки ).

total=0.0

while read -r line; do
    t=$(/usr/bin/time -f "%e" $line 2>&1)
    total=$(awk "BEGIN{print $total+$t}")
    echo "$total $line"
done

Пример вывода:

0.1 sleep 0.1
0.3 sleep 0.2
1.3 sleep 1
2
27.01.2020, 21:08
trickle () {
    awk 'BEGIN { t = systime(); OFS="\t" }
               { print systime() - t, $0 }
               { t = systime()           }'
}

Эта небольшая функция оболочки просто оборачивает awkскрипт (, совместимый как с GNU awk, так и mawk -Wi, но не с BSD awkиз-за его отсутствияsystime()). Он будет выводить каждую строку ввода с префиксом количества полных секунд с момента последней строки вывода. Первая строка будет иметь префикс нуля.

Тестирование:

$ { echo hello; sleep 2; echo world } | trickle
0       hello
2       world

Сценарий awk, очевидно, может быть запущен и отдельно -:

$ some_command | awk 'BEGIN{OFS="\t";t=systime()}{print systime()-t,$0;t=systime()}

.

$ { echo hello; sleep 2; echo world; } | awk 'BEGIN{OFS="\t";t=systime()}{print systime()-t,$0;t=systime()}'
0       hello
2       world
5
27.01.2020, 21:08

Что ж, moreutilstsкажется идеальным инструментом для этого:

количество секунд с момента запуска:

$ seq 5 | pv -qL 1 | ts -s %s
2 1
4 2
6 3
8 4
10 5

Или с большей точностью:

$ seq 5 | pv -qL 1 | ts -s %.s
1.949228 1
3.933483 2
5.917923 3
7.902231 4
9.886618 5

Or с zshилиksh93($SECONDSпо умолчанию является целым числом, но вы можете сделать его плавающим с помощью typeset -F; pdkshи bashтакже имеют $SECONDS,но только целые):

$ typeset -F SECONDS=0; seq 5 | pv -qL 1 | while IFS= read -r line; do
   printf '%.3f %s\n' "$SECONDS" "$line"; done
1.987 1
3.972 2
5.956 3
7.941 4
9.925 5

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

$ seq 5 | pv -qL 1 | ts -i %.s
1.947814 1
1.984442 2
1.984456 3
1.984151 4
1.984195 5

zsh/ksh93:

$ seq 5 | pv -qL 1 | while SECONDS=0;  IFS= read -r line; do
  printf '%.6f %s\n' "$SECONDS" "$line"; done
1.985298 1
1.984322 2
1.984212 3
1.984240 4
1.984441 5
2
27.01.2020, 21:08

Сначала создайте простую функцию, использующую встроенную функцию bash SECONDS. Обратите внимание, что мы инициализируем его нулем при каждом вызове.

_time() { SECONDS=0; out="$($@)"; echo "[${SECONDS}] ${out:-no output}"; }

Затем используйте эту функцию _timeдля запуска вашей команды (s )из списка команд, может быть их файл или что-то еще.

while read cmd; do _time $cmd; done < <(echo -e "sleep 5\nsleep 2\nsleep 1")

Здесь у sleep нет вывода, но ваши команды, скорее всего, будут. Это просто для того, чтобы показать использование СЕКУНД в отношении этой проблемы. В этом примере будет выводиться вывод по умолчаниюno output:

[5] no output
[2] no output
[1] no output
1
27.01.2020, 21:08

Теги

Похожие вопросы