Precisa concatenar a data e o inteiro para obter o valor do tempo de data

6

Eu tenho um arquivo de dados de entrada como este, com os nomes das colunas não incluídos no arquivo de dados ( Date , Desc , Timestamp1 , Timestamp2 ):

2016-01-01, AAA, 330, 1430

2016-01-02, ABA, 130, 930

Eu preciso de uma saída assim:

2016-01-01, AAA, 2016-01-01 03:30, 2016-01-01 14:30

2016-01-02, ABA, 2016-01-02 01:30, 2016-01-02 09:30

Como isso pode ser feito?

    
por I Singh 22.05.2018 / 20:52

4 respostas

10

Isso pode ser feito com a substituição de uma string simples, como abaixo, usando awk , mas esteja ciente de que esse método provavelmente não é muito confiável se o formato mudar um pouco ou os dados de entrada não forem válidos.

awk -F, '/,/{printf "%s, %s, %s %02d:%02d, %s %02d:%02d\n",$1,$2,$1,int($3/100),$3%100,$1,int($4/100),$4%100}' YOUR_FILE.CSV

Ou com o código awk formatado para melhor legibilidade:

/,/ {
    printf "%s, %s, %s %02d:%02d, %s %02d:%02d\n",
           $1, $2, 
           $1, int($3 / 100), $3 % 100,
           $1, int($4 / 100), $4 % 100
}

Em inglês, isso é executado em cada linha que contém uma vírgula (para evitar o processamento de linhas vazias) e apenas imprime os respectivos valores de coluna (a entrada é separada por vírgula devido a -F, ) com o formato especificado:

  • 1ª coluna (data), vírgula, 2a coluna (desc), vírgula,
  • 1ª coluna (data), 3ª coluna valor / 100 (hora da data e hora1), dois pontos, 3ª coluna com valor módulo 100 (minutos da data e hora1), vírgula
  • 1a coluna (data), 4º valor da coluna / 100 (hora do registro de data e hora2), dois pontos, quarto valor da coluna módulo 100 (minutos de registro de data e hora2)

O resultado nos seus dados de entrada em questão seria

2016-01-01,  AAA, 2016-01-01 03:30, 2016-01-01 14:30
2016-01-02,  ABA, 2016-01-02 01:30, 2016-01-02 09:30
    
por Byte Commander 22.05.2018 / 21:30
6

Você pode usar awk para alcançar a saída desejada. Não tenho certeza se as linhas em branco entre a entrada e a saída estão realmente lá ou apenas um problema de formatação, mas eu as considerei no comando.

awk -F, '{if (NF) { print $1 "," $2 ", " $1 " " sprintf("%02d", int($3 / 100)) ":" $3 % 100 ", " $1 " " sprintf("%02d", int($4 / 100)) ":" $4 % 100 } else { print }}' < input.txt > output.txt

O que isto faz é o seguinte:

  • -F, define o separador do campo de entrada de awk para , , portanto a entrada é dividida corretamente.
  • if (NF) verifica se o número de campos de entrada é maior que zero. Isto é para o manuseio de linhas vazias. Se a linha estiver vazia, a parte else no final do comando imprimirá uma linha em branco.
  • O comando print imprime os campos especificados:
    • $1 é o primeiro campo da entrada, a data
    • "," imprime uma vírgula literal
    • $2 é o segundo campo, a descrição
    • ", " imprime a próxima vírgula
    • $1 imprime a data novamente para seu timestamp
    • " " adiciona o espaço entre a data e a hora
    • sprintf("%02d", int($3 / 100)) primeiro calcula a parte da hora dividindo a hora por 100, descartando os decimais ( int() faz isso) e imprime esse número com zeros à esquerda com dois dígitos ( %02d% como string de formatação para sprintf() handles isso)
    • ":" é novamente apenas um cólon literal
    • $3 % 100 é uma operação de módulo dando o restante da divisão do tempo por 100 e, portanto, os minutos
    • ", " $1 " " sprintf("%02d", int($4 / 100)) ":" $4 % 100 é o mesmo para o segundo timestamp
  • else parte é explicada acima com o if .
  • < input.txt diz ao shell para ler a entrada awk s do arquivo especificado.
  • > output.txt diz ao shell para gravar a saída awk s para esse arquivo.
por Lienhart Woitok 22.05.2018 / 21:28
4

Aqui está uma variante perl (cujo s/pattern/replacement/ tem um modificador e que permite a avaliação de uma expressão na substituição):

perl -F', ' -lpe '$_ = join ",", @F[0,1], map { 
    s/(\d?\d)(\d\d)/sprintf "%s %02d:%02d", $F[0], $1, $2/e ; $_ 
  } @F[2,3] if @F
' file
2016-01-01, AAA, 2016-01-01 03:30, 2016-01-01 14:30

2016-01-02, ABA, 2016-01-02 01:30, 2016-01-02 09:30
    
por steeldriver 23.05.2018 / 01:36
0

Seguindo a versão Perl com uma estratégia get-the-basic-elements e reformatá-los

perl -ne '/((.*?),.*?, )(\d*)(\d\d), (\d*)(\d\d)/ and 
            printf("%s%s %02d:%s, %s %02d:%s\n", $1,$2,$3,$4,$2,$5,$6)'
    
por JJoao 24.05.2018 / 20:20