Если строка начинается с временной метки unix, то так и должно быть:
perl -pe 's/^(\d+)/localtime $1/e' inputfilename
perl -p
вызывает цикл над выражением, переданным с помощью -e
, который выполняется для каждой строки ввода и печатает буфер в конце цикла.
Выражение использует команду подстановки s///
для сопоставления и захвата последовательности цифр в начале каждой строки и замены ее представлением местного времени этих цифр, интерпретируемым как отметка времени unix. /e
указывает, что шаблон замены должен оцениваться как выражение.
Если ваш AWK Gawk , вы можете использоватьstrftime
:
gawk '{ print strftime("%c", $1) }'
преобразует метку времени в первом столбце в представление даты/времени по умолчанию для текущей локали.
Вы можете использовать это для преобразования контента перед его просмотром:
gawk '{ print gensub($1, strftime("%c", $1), 1) }' inputfile
использовать "дата"
Для этого вам не нужен perl, awk, php или длинное арифметическое выражение. Вы можете сделать это с помощью gnu "date", что действительно очень полезно для такого рода вещей. Для других версий «свидания» ваш YMMV.
$ date -d '1/1/1970 GMT 1571889039 seconds'
Wed Oct 23 20:50:39 PDT 2019
Здесь происходит то, что вы указываете время и корректируете его. Время — полночь 1 января 1970 года по Гринвичу, эпоха Unix. (Полночь не указана явно; он используется неявно каждый раз, когда вы опускаете время суток.)
Корректировка, 1571889039 секунд, добавляется ко времени. Вместо этого используйте свою временную метку, очевидно. В документах для этой функции используется слово «относительный».
Существует более краткая версия, документированная только примером на странице руководства, которая работает для более новых версий gnu date:
$ date -d @2147483647
Mon Jan 18 19:14:07 PST 2038
Если вам нужно часто манипулировать датами, изучите свою команду date. Это больше, чем просто часы; это библиотека даты/времени для оболочки.
Как уже было сказано, на самом деле нет портативного способа сделать это с помощью оболочки или даже АВК. GAWK может это сделать, но GAWK strftime
недоступен для некоторых версии AWK, а именно MAWK. И MAWK используется с некоторыми популярными дистрибутивами, для например Дебиан.
Я согласен, что для этого должна быть доступна портативная оболочка или решение AWK. Но так как это не так и, вероятно, не будет в течение многих лет, если вообще когда-либо, лучшее решение - просто используйте язык программирования. Был предложен Perl, другой вариант — PHP :
.$ cat input.txt
1571806800 blue
1571720400 green
1571634000 orange
1571547600 red
1571461200 yellow
$ cat app.php
<?php
$r1 = fopen('input.txt', 'r');
while (true) {
$s1 = fgets($r1);
if ($s1 === false) {
break;
}
$a1 = explode(' ', $s1);
$n1 = + $a1[0];
echo date(DATE_W3C, $n1), "\n";
}
$ php app.php
2019-10-23T05:00:00+00:00
2019-10-22T05:00:00+00:00
2019-10-21T05:00:00+00:00
2019-10-20T05:00:00+00:00
2019-10-19T05:00:00+00:00
Как Дэн упоминает в своем ответе , команду Gnu date(1)
можно задан параметр -d
с датой или отметкой времени, который он будет рассматривать как дата, которую необходимо вывести. (Это недоступно в POSIX или BSD. date(1)
команды, однако.)@1571806800
— это формат, используемый для укажите целое число time_t
.
Вот функция оболочки Bash, которая действует как фильтр, читая строки из ввод, предполагая, что любое слово, начинающееся со строки, состоящей только из цифр, является отметку времени и преобразовать ее в удобочитаемый -вывод в одном из моих любимые форматы.
ts2hr() {
while read n rest; do
if [[ $n =~ ^[0-9][0-9]*$ ]]; then
echo "$(date -d @"$n" +"%Y-%m-%d %T")" "$rest"
else
echo "$n" "$rest"
fi
done
}
Вот как выглядят некоторые входные и выходные данные:
ts2hr <<____
1571806123 first line
# A comment?
1571720456 second date's here
Just a regular sentence.
1571547789 The last line.
____
2019-10-23 13:48:43 first line
# A comment?
2019-10-22 14:00:56 second date's here
Just a regular sentence.
2019-10-20 14:03:09 The last line.
Вы можете настроить функцию по мере необходимости для обработки конкретного ввода. и форматы вывода, которые вам нужны, а также инструменты, которые у вас есть доступный. Вышеупомянутая функция является Bash главным образом потому, что оператор =~
упростили сопоставление с образцом; если вам это нужно в оболочке Bourne, вы придется закодировать чек по-другому, если он вам вообще нужен.
Если у вас нет даты gnu или доступа к языку программирования с помощью strftime или его эквивалента, вам придется выполнять математические расчеты самостоятельно, что выходит за рамки кодового гольфа.
unix_to_iso_utc () {
local day_unix=$(($1 / 86400))
local day_offset=$(($1 % 86400))
local d=$(($day_unix + 719468))
local y=$((($d - ($d+2+3*$d/146097)/1461 + ($d-$d/146097)/36524 - ($d+1)/146097)/365))
local y_d=$((365*$y + $y/4 - $y/100 + $y/400))
local y_offset=$(($d - $y_d))
local m=$((($y_offset - ($y_offset+20)/50) / 30))
local m_d=$((30*$m + 3*($m+4)/5 - 2))
local day=$(($y_offset - $m_d + 1))
local m_cont=$((12*$y + $m + 2))
local year=$(($m_cont/12))
local month=$(($m_cont%12 + 1))
local hour=$(($day_offset / 3600))
local hour_offset=$(($day_offset % 3600))
local minute=$(($hour_offset / 60))
local second=$(($hour_offset % 60))
DATE=$(printf "%04d-%02d-%02dT%02d:%02d:%02d" $year $month $day $hour $minute $second)
}
Вероятно, на тот момент у вас также не было базы данных часовых поясов, что может стать серьезной практической проблемой, если только вы не сможете жестко запрограммировать то, что вам нужно.