Есть ли утилита Unix для добавления временных меток к стандартному вводу?

StackOverflow https://stackoverflow.com/questions/21564

  •  09-06-2019
  •  | 
  •  

Вопрос

В итоге я написал для этого небольшой скрипт на Python, но мне было интересно, существует ли утилита, в которую можно было бы вводить текст, которая добавляла бы к каждой строке какой-нибудь текст - в моем конкретном случае - временную метку.В идеале использование будет примерно таким:

cat somefile.txt | prepend-timestamp

(Прежде чем вы ответите, я попробовал это:

cat somefile.txt | sed "s/^/`date`/"

Но при этом команда date оценивается только один раз при выполнении sed, поэтому перед каждой строкой неправильно добавляется одна и та же метка времени.)

Это было полезно?

Решение

Можно попробовать использовать awk:

<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }'

Возможно, вам придется убедиться, что <command> производит вывод с буферизацией строк, т.е.он очищает выходной поток после каждой строки;временная метка awk adds будет временем появления конца строки во входном канале.

Если awk показывает ошибки, попробуйте gawk вместо.

Другие советы

ts от дополнительные утилиты будет добавлять временную метку к каждой строке ввода, которую вы ей вводите.Вы также можете отформатировать его с помощью strftime.

$ echo 'foo bar baz' | ts
Mar 21 18:07:28 foo bar baz
$ echo 'blah blah blah' | ts '%F %T'
2012-03-21 18:07:30 blah blah blah
$ 

Чтобы установить его:

sudo apt-get install moreutils

комментировать, доступный по этой ссылке или как annotate-output в Дебиане devscripts упаковка.

$ echo -e "a\nb\nc" > lines
$ annotate-output cat lines
17:00:47 I: Started cat lines
17:00:47 O: a
17:00:47 O: b
17:00:47 O: c
17:00:47 I: Finished with exitcode 0

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

unbuffer $COMMAND | ts

В Ubuntu они поступают из пакетовexpect-dev и moreutils.

sudo apt-get install expect-dev moreutils

Как насчет этого?

cat somefile.txt | perl -pne 'print scalar(localtime()), " ";'

Судя по вашему желанию получать временные метки в реальном времени, возможно, вы хотите оперативно обновлять файл журнала или что-то в этом роде?Может быть

tail -f /path/to/log | perl -pne 'print scalar(localtime()), " ";' > /path/to/log-with-timestamps

Просто выкину это сюда:есть пара утилит в DAEMON Tools называется тай64н и тай64нлокальный которые созданы для добавления временных меток к регистрации сообщений.

Пример:

cat file | tai64n | tai64nlocal

Ответ Кирона на данный момент лучший.Если у вас возникли проблемы из-за того, что первая программа выполняет буферизацию, вы можете использовать программу unbuffer:

unbuffer <command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'

Он установлен по умолчанию в большинстве Linux-систем.Если вам нужно собрать его самостоятельно, это часть ожидаемого пакета.

http://expect.nist.gov

Используйте команду read(1) для чтения по одной строке из стандартного ввода, а затем выведите строку с добавленной датой в выбранном вами формате с помощью date(1).

$ cat timestamp
#!/bin/sh
while read line
do
  echo `date` $line
done
$ cat somefile.txt | ./timestamp

Я не разбираюсь в Unix, но думаю, вы можете использовать

gawk '{print strftime("%d/%m/%y",systime()) $0 }' < somefile.txt
#! /bin/sh
unbuffer "$@" | perl -e '
use Time::HiRes (gettimeofday);
while(<>) {
        ($s,$ms) = gettimeofday();
        print $s . "." . $ms . " " . $_;
}'

Вот мое решение awk (из системы Windows/XP с инструментами MKS, установленными в каталоге C:\bin).Он предназначен для добавления текущей даты и времени в формате мм/дд чч:мм в начало каждой строки, получая эту метку времени из системы при чтении каждой строки.Конечно, вы можете использовать шаблон BEGIN, чтобы один раз получить метку времени и добавить ее к каждой записи (все равно).Я сделал это, чтобы пометить файл журнала, который создавался на стандартный вывод, меткой времени на момент создания сообщения журнала.

/"pattern"/ "C\:\\\\bin\\\\date '+%m/%d %R'" | getline timestamp;
print timestamp, $0;

где «шаблон» — это строка или регулярное выражение (без кавычек), которые должны быть сопоставлены во входной строке, и является необязательным, если вы хотите сопоставить все входные строки.

Это также должно работать в системах Linux/UNIX, просто избавьтесь от C\:\\bin\\, оставив строку

             "date '+%m/%d %R'" | getline timestamp;

Это, конечно, предполагает, что команда «date» приведет вас к стандартной команде отображения/установки даты Linux/UNIX без конкретной информации о пути (т. е. переменная PATH вашей среды правильно настроена).

Смешивание некоторых ответов выше из натевв и Фрэнк Ч.Эйглер.

Он имеет миллисекунды, работает лучше, чем вызов внешнего date команду каждый раз, а Perl можно найти на большинстве серверов.

tail -f log | perl -pne '
  use Time::HiRes (gettimeofday);
  use POSIX qw(strftime);
  ($s,$ms) = gettimeofday();
  print strftime "%Y-%m-%dT%H:%M:%S+$ms ", gmtime($s);
  '

Альтернативная версия со сбросом и циклическим чтением:

tail -f log | perl -pne '
  use Time::HiRes (gettimeofday); use POSIX qw(strftime);
  $|=1;
  while(<>) {
    ($s,$ms) = gettimeofday();
    print strftime "%Y-%m-%dT%H:%M:%S+$ms $_", gmtime($s);
  }'
$ cat somefile.txt | sed "s/^/`date`/"

вы можете сделать это (с ГНУ/СЭД):

$ some-command | sed "x;s/.*/date +%T/e;G;s/\n/ /g"

пример:

$ { echo 'line1'; sleep 2; echo 'line2'; } | sed "x;s/.*/date +%T/e;G;s/\n/ /g"
20:24:22 line1
20:24:24 line2

конечно, вы можете использовать и другие возможности программы дата.просто замените date +%T с тем, что вам нужно.

Ответ Каервина можно запустить как подпрограмму, которая предотвратит новые процессы в каждой строке:

timestamp(){
   while read line
      do
         echo `date` $line
      done
}

echo testing 123 |timestamp

Отказ от ответственности:решение, которое я предлагаю, не является встроенной утилитой Unix.

Я столкнулся с подобной проблемой несколько дней назад.Мне не понравился синтаксис и ограничения приведенных выше решений, поэтому я быстро собрал программу на Go, которая сделала всю работу за меня.

Вы можете проверить инструмент здесь: предварительный тайм

В каталоге имеются готовые исполняемые файлы для Linux, MacOS и Windows. Релизы раздел проекта GitHub.

Инструмент обрабатывает неполные строки вывода и имеет (с моей точки зрения) более компактный синтаксис.

<command> | preftime

Это не идеально, но я бы поделился им, если это кому-то поможет.

делать это с date и tr и xargs на OSX:

alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S\" | tr \"\n\" \" \"; echo \"{}\"'"
<command> | predate

если вам нужны миллисекунды:

alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"

но учтите, что в OSX date не дает вам опции %N, поэтому вам нужно будет установить gdate (brew install coreutils) и, наконец, пришли к следующему:

alias predate="xargs -I{} sh -c 'gdate +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"

Если значение, которое вы добавляете в начало, одинаково во всех строках, запустите emacs с файлом, а затем:

Ctrl + <пробел>

в начале файла (чтобы отметить это место), затем прокрутите вниз до начала последней строки (Alt + > перейдет в конец файла...что, вероятно, также потребует нажатия клавиши Shift, затем Ctrl + a, чтобы перейти к началу этой строки) и:

Ctrl + Икс р т

Какую команду следует вставить в только что указанный вами прямоугольник (прямоугольник шириной 0).

21 августа 2008 г., 18:45 <введите>

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

ОБНОВЛЯТЬ:Я только что понял, что тебе не нужна одна и та же дата, так что это не сработает...хотя вы можете сделать это в emacs с помощью немного более сложного пользовательского макроса, но, тем не менее, о таком виде редактирования прямоугольников довольно приятно знать...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top