Eu tenho um arquivo com os seguintes dados de amostra de entrada:
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
a primeira coluna é o carimbo de data e hora da época unix que preciso converter para um formato legível por humanos e quero que os dados sejam delimitados da seguinte forma
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
tentei adicionar delimitadores usando sed 's/ {1,}/|/g' e convertendo a data usando date -d @1137921146.499. Mas não consigo juntar esses dois em um comando.
Responder1
Você pode usar o programa awk assim:
awk '{ print strftime("%c",$1)"|" $2"|"$3"|"$4 }' file
o núcleo é usar a função strftime para converter a época para o formato de data
Aqui está a saída:
#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
PS Ou você pode usar o delimitador de saída implícito:
awk 'BEGIN { OFS="|"} {$1= strftime("%c",$1) }1' file
Responder2
Usando o que você já sabe:
- GNU
date
pode converter um carimbo de data/hora em uma data formatada fornecendo-lhe@timestamp
. - Substituir espaços por
|
fornecerá a saída desejada.
A isso, adicionamos
- GNU
date
pode operar em um arquivo, convertendo datas em um lote.
Para converter datas em lote com GNU, date
temos que extrair os carimbos de data e hora e prefixá-los com @
:
$ sed 's/^\([^ ]*\).*$/@\1/' data.in
@1137921146.499
@1137921158.698
@1137921758.163
@1137921802.016
A sed
expressão substitui cada linha pelo primeiro campo delimitado por espaço prefixado com @
.
Com bash
(e ksh93
, ou qualquer shell que entenda substituições de processos):
$ 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
Depois precisamos pegar os outros campos dos dados de entrada e substituir os delimitadores:
$ 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
Em seguida, colamos essas duas coisas juntas com um |
delimitador 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
Responder3
Ou com seu shell:
while read timestamp pid ip port; do
echo "$(date -d @$timestamp)|$pid|$ip|$port"
done <yourfile