Pegue uma string e coloque-a no começo de uma linha até que a próxima string seja encontrada

3

Eu tenho um grande arquivo xhtml não-padrão que estou usando sed (cerca de 4 vezes) para percorrer apenas os fundamentos que eu preciso para jogar os dados em um banco de dados MySQL. Meu último pedaço estou lutando com. O arquivo é formatado como:

 Tue Aug 18 2015
0,0,0,0,0
0,0,0,2,275
0,0,0,3,287
0,0,0,0,327
0,0,0,3,335
0,0,0,0,413
 Wed Aug 19 2015
0,0,0,0,0
0,0,0,2,275
0,0,0,3,287
0,0,0,2,308
 Thu Aug 20 2015
0,0,0,0,0
0,0,0,2,458
0,0,0,3,469
0,0,0,0,472
0,0,0,3,503
0,0,0,2,534

Existe sempre um espaço antes do dia. Pode haver qualquer número de linhas de valor CSV após a data.

O que eu espero que seja alcançado é:

Tue Aug 18 2015,0,0,0,0,0
Tue Aug 18 2015,0,0,0,2,275
Tue Aug 18 2015,0,0,0,3,287
Tue Aug 18 2015,0,0,0,0,327
Tue Aug 18 2015,0,0,0,3,335
Tue Aug 18 2015,0,0,0,0,413
Wed Aug 19 2015,0,0,0,0,0
Wed Aug 19 2015,0,0,0,2,275
Wed Aug 19 2015,0,0,0,3,287
Wed Aug 19 2015,0,0,0,2,308
Thu Aug 20 2015,0,0,0,0,0
Thu Aug 20 2015,0,0,0,2,458
Thu Aug 20 2015,0,0,0,3,469
Thu Aug 20 2015,0,0,0,0,472
Thu Aug 20 2015,0,0,0,3,503
Thu Aug 20 2015,0,0,0,2,534

e, se for possível, retirar o dia e adicionar mais algumas vírgulas para facilitar a manipulação em um script PHP, como:

Aug,18,2015,0,0,0,0,0
Aug,18,2015,0,0,0,2,275
Aug,18,2015,0,0,0,3,287
Aug,18,2015,0,0,0,0,327
Aug,18,2015,0,0,0,3,335
Aug,18,2015,0,0,0,0,413
Aug,19,2015,0,0,0,0,0
Aug,19,2015,0,0,0,2,275
Aug,19,2015,0,0,0,3,287
Aug,19,2015,0,0,0,2,308
Aug,20,2015,0,0,0,0,0
Aug,20,2015,0,0,0,2,458
Aug,20,2015,0,0,0,3,469
Aug,20,2015,0,0,0,0,472
Aug,20,2015,0,0,0,3,503
Aug,20,2015,0,0,0,2,534

Existem alguns comandos que podem ser usados?

Ainda sou muito novo no processamento em lote de linha de comando do texto. Se possível, você poderia incluir uma pequena ajuda sobre o que cada parte do comando faz para que eu possa descobrir como fazer isso sozinho na próxima vez?

    
por Nick Twigg 25.05.2016 / 23:55

2 respostas

3

Aqui está uma maneira de fazer isso:

sed '/,/!{                       # if there's no comma on this line
y/ /,/                           # translate spaces to commas
h                                # copy pattern space over the hold buffer
d                                # delete pattern space
}
//{                              # if the line contains commas
G                                # append hold space content to pattern space
s/\(.*\)\n,[^,]*,\(.*\)/,/   # swap lines removing newline, the day part and
}                                # first two commas and adding a comma after year
' infile

Se preferir um gnu sed one-liner:

sed -E '/,/!{y/ /,/;h;d};//{G;s/(.*)\n,[^,]*,(.*)/,/}' infile

É semelhante com awk :
Se a linha não contiver vírgulas, você pode formatar a data via sprintf , salvar o resultado em uma variável, por exemplo, dt e depois vá para next record. Senão prefixar dt a $0 (essa é a linha atual):

awk '!/,/{dt=sprintf("%s,%s,%s,", $2, $3, $4);next};$0=dt$0' infile
    
por 26.05.2016 / 00:50
0
awk -F, -v OFS=, '/^[[:blank:]]+/ {
                      str=gensub(/ /,",","g",$0);
                      sub(/^,+[^,]+,/,"",str);
                      next
                  };

                  !/^[[:blank:]]+/ {print str,$0}' nick.txt

(isso pode, claro, ser tudo em uma linha. Escrevi e testei como uma linha única e, em seguida, adicionei feeds de linha e recuo para torná-lo mais legível aqui)

Para linhas que começam com um ou caracteres em branco (ou seja, espaços ou tabulações), esse script awk converte todos os espaços em vírgulas, salva a linha modificada em uma variável chamada str e remove as vírgulas iniciais ) e todo o texto até e incluindo a próxima vírgula.

Para linhas que não começam com caractere em branco, ele imprime a linha precedida com o valor atual de str .

Aviso: se houver linhas de dados CSV antes da primeira linha de data, essas linhas serão impressas apenas com uma única vírgula como prefixo.

Saída:

Aug,18,2015,0,0,0,0,0
Aug,18,2015,0,0,0,2,275
Aug,18,2015,0,0,0,3,287
Aug,18,2015,0,0,0,0,327
Aug,18,2015,0,0,0,3,335
Aug,18,2015,0,0,0,0,413
Aug,19,2015,0,0,0,0,0
Aug,19,2015,0,0,0,2,275
Aug,19,2015,0,0,0,3,287
Aug,19,2015,0,0,0,2,308
Aug,20,2015,0,0,0,0,0
Aug,20,2015,0,0,0,2,458
Aug,20,2015,0,0,0,3,469
Aug,20,2015,0,0,0,0,472
Aug,20,2015,0,0,0,3,503
Aug,20,2015,0,0,0,2,534
    
por 26.05.2016 / 07:28