bash - печатать строку каждые X секунд (как sed каждые X строк) - PullRequest
1 голос
/ 09 февраля 2020

Я знаю, с помощью sed вы можете передать вывод команды так, чтобы вы могли print every X lines.
make all | sed -n '2~5'

Существует ли эквивалентная команда для print a line every X seconds?
make all | print_line_every_sec '5'

Ответы [ 5 ]

2 голосов
/ 09 февраля 2020

Через 5 секунд прочитайте одну строку и откажитесь от всего остального:

while
   # timeout 5 seconds
   ! timeout 5 sh -c '
     # read one line
     if IFS= read -r line; then
        # output the line
        printf "%s\n" "$line"
        # discard the input for the rest of 5 seconds
        cat >/dev/null
     fi
     # will get here only, if there is nothing to read
   '
   # that means that `timeout` will always return 124 if stdin is still open
   # and it will return 0 exit status only if there is nothing to read
   # so we loop on nonzero exit status of timeout.
do :; done

и отдельного:

while ! timeout 0.5 sh -c 'IFS= read -r line && printf "%s\n" "$line" && cat >/dev/null'; do :; done

Но, может быть, что-то попроще - просто отбрасывайте 5 секунд данных каждый строка:

while IFS= read -r line; do
    printf "%s\n" "$line"
    timeout 5 cat >/dev/null
done

или

while IFS= read -r line && 
    printf "%s\n" "$line" &&
    ! timeout 5 cat >/dev/null
do :; done
0 голосов
/ 10 февраля 2020

Это может работать для вас (GNU sed):

sed 'e sleep 1' file

Печать строки каждые n (в приведенном выше примере 1) секунды.

Для печати 5 строк каждые 2 секунды, использование:

sed '1~5e sleep 2' file
0 голосов
/ 10 февраля 2020

Даже если предложенные решения интересны и красивы, самое элегантное решение ИМХО - это решение awk . Если вы хотите выдать

make all | print_line_every_sec 5

, вам нужно создать скрипт print_line_every_se c следующим образом, включая тест, чтобы избежать бесконечного l oop:

#!/bin/bash

if [ $1 -le 0 ] ; then echo $(basename $0): invalid argument \'$1\'; exit 1; fi

awk -v delay=$1 'BEGIN {t = systime ()}
  {if (systime() >= t) {print $0 ; t += delay}}'
0 голосов
/ 10 февраля 2020

Если вы хотите получать самое последнее сообщение каждые 5 секунд, попробуйте:

make all | {
    display(){
        if  (( $SECONDS >= 5)); then
            if  test -n "${last_line+x}"; then
                # print only if there is a message in the last 5 seconds
                echo $last_line; unset last_line
            fi
            SECONDS=0
        fi
    }
    SECONDS=0
    while true; do
        while IFS= read -t 0.001 line; do
            last_line=$line
            display
        done
        display
    done
}
0 голосов
/ 09 февраля 2020

Вы можете сделать это командой watch. Если вам нужно печатать вывод только каждую X секунду, вы можете использовать что-то вроде этого:

watch -n X "Your CMD"

, если вам нужно указать какое-либо изменение в вашем выводе, было бы полезно использовать переключатель -d:

watch -n X -d "Your CMD"
...