br comando para trocar caracteres

5

Meu layout de arquivo de entrada é: mm/dd/yyyy,hh:mm,other fields
Eu preciso formatá-lo como: yyyy-mm-dd hh:mm:00,other fields

entrada de amostra:

01/02/1998,09:30,0.4571,0.4613,0.4529,0.4592,6042175
01/02/1998,09:45,0.4592,0.4613,0.4529,0.4571,9956023
01/02/1998,10:00,0.4571,0.4613,0.455,0.4613,8939555
01/02/1998,10:15,0.4613,0.4697,0.4571,0.4697,12823627
01/02/1998,10:30,0.4676,0.4969,0.4613,0.4906,28145145

exemplo de saída:

1998-01-02 09:30:00,0.4571,0.4613,0.4529,0.4592,6042175
etc...

Eu tentei usar:

sed -r 's/\(^[0-9][0-9])\(\/[0-9][0-9]\/)\(\/[0-9][0-9][0-9][0-9],)//g
    
por Karthik Appigatla 02.06.2015 / 13:58

6 respostas

6
sed -e 's/\(..\)\/\(..\)\/\(....\),\(.....\),\(.*\)/-- :00,/'

Editado para incluir a entrada dos comentários abaixo:

sed -e 's#\(..\).\(..\).\(....\),\(.....\),#-- :00,#'
    
por 02.06.2015 / 14:05
3

Isso funcionou para mim:

sed -r 's/([0-9]{2})\/([0-9]{2})\/([0-9]{4}),([0-9:]{5})/-- :00/g'

Corresponde a 2 dígitos ( ([0-9]{2}) ), barra, 2 dígitos ( ([0-9]{2}) ), barra, 4 dígitos ( ([0-9]{4}) ) e, em seguida, dígitos e : ( ([0-9:]{5}) ). Substitua-o pelo pedido desejado: -- :00 (ano-mês-dia hora: minuto: 00).

    
por 02.06.2015 / 14:04
3
sed 'y|/|-|
     s/,*\(.....\)-*\([^,]*\)/-/
     s// :00/2
'    <infile

OUTPUT:

1998-01-02 09:30:00,0.4571,0.4613,0.4529,0.4592,6042175
1998-01-02 09:45:00,0.4592,0.4613,0.4529,0.4571,9956023
1998-01-02 10:00:00,0.4571,0.4613,0.455,0.4613,8939555
1998-01-02 10:15:00,0.4613,0.4697,0.4571,0.4697,12823627
1998-01-02 10:30:00,0.4676,0.4969,0.4613,0.4906,28145145

Com sed , você geralmente não precisa se esforçar tanto - geralmente não vale a pena tentar enumerar explicitamente as correspondências que você está procurando. Em vez disso, é muito mais simples geralmente apenas especificar alguns pontos de referência - delimitadores - e deixar um padrão englobar o intervalo para você.

Acima de sed first y/// traduz / caracteres para - caracteres. Em seguida, ele faz referência ao primeiro caractere não-comma (desde que haja pelo menos 5) no padrão e aos quatro caracteres seguintes como , possivelmente ignorando um - à direita. Segue-se que referenciando como muitos caracteres sequenciais ^ não-vírgula em como poderia antes da próxima vírgula que está ocorrendo no espaço padrão. O resultado - para a primeira substituição - é colocar mm-dd em antes de corresponder a - e, em seguida, yyyy em . Então nós trocamos esses, soltamos o - e inserimos um novo no outro lado como:

s/.../-/

E por último fazemos novamente - reutilizando o mesmo padrão para um propósito diferente. Quando eu faço:

s// :00/2

Estou instruindo sed para reutilizar o último regexp (como representado pelo // endereço vazio) , mas desta vez para encontrar a segunda ocorrência desse padrão no espaço padrão - que faz combina uma vírgula com ,* desta vez - ela corresponde à vírgula que separa esse campo e a última. Ele também corresponde a HH:MM em e (porque essa sequência é imediatamente seguida por uma vírgula) a '' null-string em . Tudo o que resta disso é substituir por si mesmo precedido por < space > e seguido pela sequência : 00 . Tanto a vírgula interveniente como a cadeia nula são editadas.

Se você acha que seria mais específico, afinal, considere o quão mais fácil ele pode ser com apenas um pouco de abstração. O principal benefício oferecido pelas expressões regulares é que elas nos fornecem um meio de abstrair rápida e eficientemente uma tarefa repetitiva, dada apenas uma clara compreensão do que a torna repetitiva em primeiro lugar.

Se a construção do seu regexp se tornar uma tarefa repetitiva por si só, então, bem ... algo provavelmente está faltando. Uma das vantagens de uma sintaxe regexp simples, porém, é que também geralmente é um bom candidato para abstração - e é facilmente alcançável.

Por exemplo:

d='[0-9][0-9]' T=$d:$d m=$d y=$d$d
sed -E "s|($m/$d)/($y),($T)|- :00|;s|/|-|"
    
por 02.06.2015 / 14:42
2

E possível awk solution:

awk 'BEGIN { FS = OFS = ","; } { split($1, d, "/"); $2 = d[3] "-" d[1] "-" d[2] " " $2 ":00"; $1 = ""; } { for (i = 2; i < NF; i++) printf("%s", $i OFS); printf("%s", $NF ORS);}' file
    
por 02.06.2015 / 14:18
2

Gostaria de sugerir uma abordagem um pouco diferente - analisar o registro de data e hora e depois cuspir um registro de data e hora formatado. E eu usaria perl para isso:

#!/usr/bin/perl

use strict;
use warnings;

use Time::Piece;

my $input_format  = '%m/%d/%Y,%H:%M';
my $output_format = '%Y-%m-%d %H:%M:%S';

while (<>) {
    my ( $date, $time, @stuff ) = split(",");
    my $timestamp = Time::Piece->strptime( "$date,$time", $input_format );
    print join( ",", $timestamp->strftime($output_format), @stuff );
}

Que você pode reduzir para um liner assim:

perl -MTime::Piece -lne '($date,$time,@stuff) = split; print join ( ',', Time::Piece->strptime( "$date,$time", "%m/%d/%Y,%H:%M" ) -> strftime("%Y-%m-%d %H:%M:%S"), @stuff);'

Que com seus dados de amostra, é lançado:

1998-01-02 09:45:00,0.4592,0.4613,0.4529,0.4571,9956023
1998-01-02 10:00:00,0.4571,0.4613,0.455,0.4613,8939555
1998-01-02 10:15:00,0.4613,0.4697,0.4571,0.4697,12823627
1998-01-02 10:30:00,0.4676,0.4969,0.4613,0.4906,28145145
    
por 02.06.2015 / 15:05
1

Use isto:

sed -n 's_^\([^/]*\)/\([^\]*\)/\([^,]*\),\([^:]*\):\([^,]*\)_-- ::00_p' file.txt
    
por 02.06.2015 / 14:09