Преобразование столбца временной метки эпохи unix в каждой строке с помощью sed или awk

Преобразование столбца временной метки эпохи unix в каждой строке с помощью sed или awk

У меня есть файл со следующими входными данными:

1137921146.499 180900 61.153.158.197 1409 
1137921158.698 181622 61.153.158.197 1409
1137921758.163 180026 221.226.124.114 1374
1137921802.016 179485 121.13.128.132 1409

1-й столбец — это временная метка эпохи Unix, которую мне нужно преобразовать в удобочитаемый формат, а также я хочу, чтобы данные были разделены следующим образом

Sun Jan 22 01:12:26 PST 2006|180900|61.153.158.197|1409   
Sun Jan 22 01:12:38 PST 2006|181622|61.153.158.19|1409

Я пытался добавить разделители, используя sed 's/ {1,}/|/g' и преобразовав дату с помощью date -d @1137921146.499. Но я не могу объединить эти два в одну команду..

решение1

Вы можете использовать программу awk следующим образом:

awk '{ print strftime("%c",$1)"|" $2"|"$3"|"$4 }' file

суть в использовании функции strftime для преобразования эпохи в формат даты

Вот что получилось:

#awk '{ print strftime("%c",$1)"|" $2"|"$3"|"$4 }' file
Sun Jan 22 10:12:26 2006|180900|61.153.158.197|1409
Sun Jan 22 10:12:38 2006|181622|61.153.158.197|1409
Sun Jan 22 10:22:38 2006|180026|221.226.124.114|1374
Sun Jan 22 10:23:22 2006|179485|121.13.128.132|1409

P.S. Или вы можете использовать неявный разделитель вывода:

awk  'BEGIN { OFS="|"} {$1= strftime("%c",$1) }1' file

решение2

Используя то, что вы уже знаете:

  • GNU dateможет преобразовать временную метку в форматированную дату, указав ей @timestamp.
  • Заменив пробелы на , |вы получите нужный вам результат.

К этому мы добавляем

  • GNU dateможет работать с файлом, преобразуя даты за один пакет.

Для пакетного преобразования дат с помощью GNU dateнам необходимо извлечь временные метки и добавить к ним префикс @:

$ sed 's/^\([^ ]*\).*$/@\1/' data.in
@1137921146.499
@1137921158.698
@1137921758.163
@1137921802.016

Выражение sedзаменяет каждую строку первым полем, разделенным пробелом, с префиксом @.

С помощью bashksh93или любой оболочки, которая понимает подстановку процессов):

$ date -f <( sed 's/^\([^ ]*\).*$/@\1/' data.in )
Sun Jan 22 10:12:26 CET 2006
Sun Jan 22 10:12:38 CET 2006
Sun Jan 22 10:22:38 CET 2006
Sun Jan 22 10:23:22 CET 2006

Затем нам нужно взять остальные поля входных данных и заменить разделители:

$ cut -d ' ' -f 2- data.in | tr ' ' '|'
180900|61.153.158.197|1409
181622|61.153.158.197|1409
180026|221.226.124.114|1374
179485|121.13.128.132|1409

Затем мы склеиваем эти две вещи вместе, используя |разделитель as:

$ paste -d '|' <( date -f <( sed 's/^\([^ ]*\).*$/@\1/' data.in ) ) <( cut -d ' ' -f 2- data.in | tr ' ' '|' )
Sun Jan 22 10:12:26 CET 2006|180900|61.153.158.197|1409
Sun Jan 22 10:12:38 CET 2006|181622|61.153.158.197|1409
Sun Jan 22 10:22:38 CET 2006|180026|221.226.124.114|1374
Sun Jan 22 10:23:22 CET 2006|179485|121.13.128.132|1409

решение3

Или с помощью оболочки:

while read timestamp pid ip port; do
  echo "$(date -d @$timestamp)|$pid|$ip|$port"
done <yourfile

Связанный контент