Seguem mais uma rotina em shell script (e R) para editar um arquivo CSV no formato desejado. O outro conjunto de scripts, com comandos para baixar um arquivo e converter de XLS para CSV, pode ser visto no post Como baixar dados em planilha e arrumar para arquivo de texto. Caso o arquivo tenha macros que referenciam o conteúdo das células, ele precisa ser aberto no Libre Office e salvo manualmente no formato CSV.
– split_files.sh
O algoritmo do script abaixo deve criar um arquivo para cada posto (partindo de um arquivo só com todos os dados) e chamar outro script (em R) para reorganizar os dados de cada arquivo. Para cada linha do arquivo “vazoes.csv”, ele busca o código do posto, que é o único elemento que está entre parênteses no documento. Se essa busca não retornar vazio, significa que encontrou a identificação de algum posto. O conteúdo das linhas sempre é gravado em um arquivo de saída. O truque para não sobrescrever e gerar um arquivo igual ao original é usar a variável “n” como identificação do posto para nomear o arquivo de destino. Assim, toda a saída é direcionada para um arquivo cujo nome é definido pela variável “n”, que identifica de qual posto são os dados.
#!/bin/bash # Ficar atento para possíveis alterações na formatação, como pontos separando milhar oldIFS=$IFS # backup do separador de campo IFS=$'\n' # novo separador de campo, o caractere de fim de linha for linha in $(cat vazoes.csv); do # pegar campo entre parênteses para entrar como nome de arquivo "posto_$n.csv" n=$(echo $linha | grep -o -P '(?<=\().*(?=\))') if [ ! -z "$n" ]; then echo $n filename='temp_'$n'.txt' fi echo $linha >> $filename done # Comando alternativo às linhas anteriores #awk '/,,,,,,,,,,,,,/{filename=NR".txt"}; {print >filename}' vazoes.csv # Formatar para "Data,Vazao"; 1931-01-01,178 (p. ex) for file in $(ls $DIR/temp_*.txt); do echo $file n=$(echo $file | grep -o [0-9]*) Rscript $DIR'/split_columns.R' $file $DIR'/posto_'$n'.csv' done rm temp_*.txt
O comando alternativo comentado no código é uma opção para separar o conteúdo do arquivo original em vários arquivos conforme um padrão de texto. Nesse caso, o padrão que aparece é uma sequência de 13 vírgulas: tudo o que está a partir desse padrão até o seguinte (excluindo esse) será impresso em um arquivo cujo nome terá o número da linha seguido de “.txt”. Como nesse caso a numeração dos postos segue outra sequência numérica, foi adotada a solução acima para o nome do arquivo já ficar com a identificação do posto.
– split_columns.R
O arquivo de entrada possui dados onde as colunas identificam os meses e a média anual (última coluna, que deve ser desconsiderada), enquanto que as linhas representam os anos e mais três estatísticas mensais (últimas linhas, que devem ser desconsideradas). A ideia desse script é de, primeiro, ler o arquivo CSV pulando a primeira linha e considerando a segunda como o cabeçalho da tabela, gravada com o nome “matriz” – nesse ponto, poderia ser utilizada a primeira coluna (com ano e identificações de estatística) como nome das linhas, mas essa ideia só tive depois. Então, é criada uma matriz vazia, chamada de “final”, para receber os valores da matriz de dados, chamada “matriz”, no formato “Data,Vazao”, ou seja, “1931-01-01,178”, por exemplo. Finalmente, essa matriz final é gravada no aquivo com o número de identificação do posto.
# Recebe variáveis args <- commandArgs(trailingOnly = TRUE) file_in = args[1] file_out = args[2] # Ler arquivo matriz = read.csv(file_in, skip=1, header=TRUE, sep=",") # Criar variaveis dia = "01" nlinhas = (nrow(matriz)-3)*12 final = matrix(nrow = nlinhas, ncol = 2) n = 1 # Gravar tabela final com dados da matriz for (linha in 1:(nrow(matriz)-3)){ ano = matriz[linha,1] for (coluna in 2:(ncol(matriz)-1)){ mes = coluna - 1 anomesdia = paste(ano,sprintf("%02d",mes),dia,sep='-') dado = matriz[linha,coluna] final[n,1] = anomesdia final[n,2] = dado n = n + 1 } } colnames(final) = c('Data','Vazao') # Gravar arquivo write.table(final, file_out, quote = FALSE, row.names = FALSE, col.names = TRUE, sep = ',')
Note que, para forçar o mês ser gravado sempre com dois dígitos (com um zero à esquerda), é utilizado o comando “sprintf(“%02d”,mes)”.
Gravar um arquivo XLS por linha de comando
O gnumeric, gerenciador de planilhas do projeto GNOME, possui o comando “ssconvert” para gravar arquivo .xls e .xlsx a partir de arquivos .csv. Para isso, instale o gnumeric (comando “sudo apt-get install gnumeric”) caso não tenha o programa já instalado. Para converter o arquivo exemplo.csv para XLS, basta usar o comando “ssconvert exemplo.csv exemplo.xls”.
Também é possível converter vários arquivos CSV como sendo planilhas de um mesmo arquivo XLS usando a opção “–merge-to=exemplo.xls”. O nome de cada arquivo será o título da planilha dentro do arquivo, então fica a dica de renomear os arquivos antes de executar o comando. Mais opções no manual do ssconvert.
One comment