Есть ли утилита Unix для добавления временных меток к стандартному вводу?
Вопрос
В итоге я написал для этого небольшой скрипт на 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-систем.Если вам нужно собрать его самостоятельно, это часть ожидаемого пакета.
Используйте команду 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 с помощью немного более сложного пользовательского макроса, но, тем не менее, о таком виде редактирования прямоугольников довольно приятно знать...