С вашим входным файлом:
perl -MTime::Piece -pe '
s{ \b (\d{10}) \d{3}\b }
{ localtime($1)->strftime("%F %T") }xge
' file1
Foo bar 2014-04-14 13:37:20 foo 1526 bar foobar, bar 2014-04-14 13:37:40.
Bar, 2013-01-05 12:30:40 foo 10 foobar.
Использование GNU awk
с функциями match()
, substr()
и strftime()
. Просканируйте заданную строку, чтобы идентифицировать записи с 10 или более цифрами, поскольку они будут отметками времени EPOCH.
В этих записях извлеките только первые 10 цифр и передайте их функции strftime()
и при необходимости примените формат даты. Замените исходную запись новой меткой времени с помощью функции sub()
.
awk '
{
for(col=1; col<=NF; col++) {
if ( match($col, /[[:digit:]]{10,}/) ) {
sub( substr($col, RSTART, RLENGTH),
strftime("%Y-%m-%d %H:%M:%S", substr($col, RSTART, RLENGTH-3) ) )
}
}
}1' file1
Предполагая, что вы хотите, чтобы мы игнорировали лишние цифры и ограничили преобразование даты только 1-й десяткой, что означало бы, что дата не находится в будущем на сотни тысяч лет, вы можете сделать это с помощью GNU date
иperl
:
$ perl -pe 's/\b(\d{10})\d{3}\b/chomp($i=`date -d \@$1 "+%F %T"`);$i/eg' file1
Foo bar 2014-04-14 18:37:20 foo 1526 bar foobar, bar 2014-04-14 18:37:40.
Bar, 2013-01-05 17:30:40 foo 10 foobar.
Решение Гленна чище и более переносимо, поэтому, если вы не возражаете против использования Perl-модуля (и не должны ), я бы порекомендовал его вместо моего.
Что касается вашей sed
попытки, чтобы использовать результат команды, вам нужно использовать обратные кавычки или $(command)
. Так что вы были почти там:
$ sed -E "s/([0-9]{10})/$(date -d @\1)/" file1
Foo bar Thu 01 Jan 1970 01:00:01 AM BST418 foo 1526 bar foobar, bar 1397497060518.
Bar, Thu 01 Jan 1970 01:00:01 AM BST418 foo 10 foobar.
Конечно, это не удаляет лишние цифры и не ограничивает число только 13 -цифрами, но поскольку вы не уточнили, что вам нужно, я не знаю, как это исправить. Мое решение Perl имеет дело с этим, поэтому вы можете использовать sed, если не хотите их удалять.