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

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

cat somefile.txt | prepend-timestamp

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

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

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

Ответ 1

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

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

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

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

Ответ 2

ts from moreutils будет добавлять временную метку к каждой строке ввода, которую вы ей даете. Вы также можете форматировать его с помощью 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

Ответ 3

annotate, доступный по этой ссылке или как annotate-output в пакете Debian 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

Ответ 4

Переопределение заданных ответов на самый простой:

unbuffer $COMMAND | ts

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

sudo apt-get install expect-dev moreutils

Ответ 5

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

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

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

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

Ответ 6

Просто выброшу это: в daemontools есть две утилиты: tai64n и tai64nlocal, которые сделаны для добавления временных меток для записи сообщений.

Пример:

cat file | tai64n | tai64nlocal

Ответ 7

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

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

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

http://expect.nist.gov

Ответ 8

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

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

Ответ 9

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

gawk '{print strftime("%d/%m/%y",systime()) $0 }' < somefile.txt

Ответ 10

#! /bin/sh
unbuffer "[email protected]" | perl -e '
use Time::HiRes (gettimeofday);
while(<>) {
        ($s,$ms) = gettimeofday();
        print $s . "." . $ms . " " . $_;
}'

Ответ 11

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

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

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

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

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

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

Ответ 12

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

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

echo testing 123 |timestamp

Ответ 13

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

вы можете сделать это (с помощью gnu/sed):

$ 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 тем, что вам нужно.

Ответ 14

делает это с помощью 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 дата не дает вам опцию% N, поэтому вам нужно установить gdate (brew install coreutils) и, наконец, прийти к такому:

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

Ответ 15

Смешивание некоторых ответов выше от natevw и Frank Ch. Eigler.

Он имеет миллисекунды, работает лучше, чем вызов внешней команды 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);
  }'

Ответ 16

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

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

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

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

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

<command> | preftime

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

Ответ 17

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

Ctrl + <space>

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

Ctrl + x r t

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

2008-8-21 6:45 PM <enter>

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

UPDATE: я просто понял, что вы не хотите SAME date, так что это не сработает... хотя вы можете сделать это в emacs с немного более сложным настраиваемым макросом, но все же этот вид редактирование прямоугольника довольно приятно знать о...