sed -e 's/\(..\)\/\(..\)\/\(....\),\(.....\),\(.*\)/-- :00,/'
Editado para incluir a entrada dos comentários abaixo:
sed -e 's#\(..\).\(..\).\(....\),\(.....\),#-- :00,#'
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
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).
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|/|-|"
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
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
Use isto:
sed -n 's_^\([^/]*\)/\([^\]*\)/\([^,]*\),\([^:]*\):\([^,]*\)_-- ::00_p' file.txt