Есть ли утилита 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 с немного более сложным настраиваемым макросом, но все же этот вид редактирование прямоугольника довольно приятно знать о...