Como analisar dados CSV no Bash

Publicados: 2022-09-16
Jane Kelly/Shutterstock.com

Os arquivos de valores separados por vírgula (CSV) são um dos formatos mais comuns para dados exportados. No Linux, podemos ler arquivos CSV usando comandos Bash. Mas pode ficar muito complicado, muito rapidamente. Nós vamos dar uma mão.

O que é um arquivo CSV?

Um arquivo de valores separados por vírgula é um arquivo de texto que contém dados tabulados. CSV é um tipo de dados delimitados. Como o nome sugere, uma vírgula “ , ” é usada para separar cada campo de dados – ou valor – de seus vizinhos.

O que é um arquivo CSV e como faço para abri-lo?
RELACIONADO O que é um arquivo CSV e como faço para abri-lo?

CSV está em toda parte. Se um aplicativo tiver funções de importação e exportação, quase sempre oferecerá suporte a CSV. Os arquivos CSV são legíveis por humanos. Você pode olhar dentro deles com menos, abri-los em qualquer editor de texto e movê-los de programa para programa. Por exemplo, você pode exportar os dados de um banco de dados SQLite e abri-lo no LibreOffice Calc.

No entanto, mesmo CSV pode se tornar complicado. Quer ter uma vírgula em um campo de dados? Esse campo precisa ter aspas “ " ”. Para incluir aspas em um campo, cada aspas precisa ser inserida duas vezes.

Claro, se você estiver trabalhando com CSV gerado por um programa ou script que você escreveu, o formato CSV provavelmente será simples e direto. Se você for forçado a trabalhar com formatos CSV mais complexos, com Linux sendo Linux, existem soluções que podemos usar para isso também.

Alguns dados de amostra

Você pode gerar facilmente alguns dados CSV de amostra, usando sites como o Online Data Generator. Você pode definir os campos que deseja e escolher quantas linhas de dados deseja. Seus dados são gerados usando valores fictícios realistas e baixados para o seu computador.

Criamos um arquivo contendo 50 linhas de informações fictícias de funcionários:

  • id : Um valor inteiro único e simples.
  • firstname : O primeiro nome da pessoa.
  • lastname : O sobrenome da pessoa.
  • job-title : o cargo da pessoa.
  • email-address : o endereço de email da pessoa.
  • branch : A filial da empresa em que trabalham.
  • state : o estado em que a filial está localizada.

Alguns arquivos CSV têm uma linha de cabeçalho que lista os nomes dos campos. Nosso arquivo de amostra tem um. Aqui está o topo do nosso arquivo:

O arquivo CSV de amostra

A primeira linha contém os nomes dos campos como valores separados por vírgulas.

Analisando dados do arquivo CSV

Vamos escrever um script que irá ler o arquivo CSV e extrair os campos de cada registro. Copie este script em um editor e salve-o em um arquivo chamado “field.sh”.

 #! /bin/bash

while IFS="," read -r id firstname sobrenome jobtitle email branch state
Faz
  echo "ID do registro: $id"
  echo "Nome: $nome"
  echo "Sobrenome: $sobrenome"
  echo "Título do trabalho: $jobtitle"
  echo "Adicionar email: $email"
  echo "Ramo: $ramo"
  echo "Estado: $estado"
  eco ""
feito < <(cauda -n +2 amostra.csv)

Há bastante coisa em nosso pequeno script. Vamos decompô-lo.

Como processar um arquivo linha por linha em um script Bash do Linux
RELACIONADO Como processar um arquivo linha por linha em um script Bash do Linux

Estamos usando um loop while . Enquanto a condição do loop while for verdadeira, o corpo do loop while será executado. O corpo do loop é bastante simples. Uma coleção de instruções echo é usada para imprimir os valores de algumas variáveis ​​na janela do terminal.

A condição do laço while é mais interessante que o corpo do laço. Especificamos que uma vírgula deve ser usada como separador de campo interno, com a instrução IFS="," . O IFS é uma variável de ambiente. O comando de read refere-se ao seu valor ao analisar sequências de texto.

Estamos usando a opção -r (reter barras invertidas) do comando read para ignorar quaisquer barras invertidas que possam estar nos dados. Eles serão tratados como personagens normais.

O texto que o comando de read analisa é armazenado em um conjunto de variáveis ​​com o nome dos campos CSV. Eles poderiam facilmente ter sido nomeados field1, field1, field2, ... field7 , mas nomes significativos tornam a vida mais fácil.

Os dados são obtidos como saída do comando tail . Estamos usando tail porque nos dá uma maneira simples de pular a linha de cabeçalho do arquivo CSV. A opção -n +2 (número da linha) diz ao tail para começar a ler na linha número dois.

A construção <(...) é chamada de substituição de processo. Isso faz com que o Bash aceite a saída de um processo como se estivesse vindo de um descritor de arquivo. Isso é então redirecionado para o loop while , fornecendo o texto que o comando de read analisará.

Torne o script executável usando o comando chmod . Você precisará fazer isso toda vez que copiar um script deste artigo. Substitua o nome do script apropriado em cada caso.

 chmod +x campo.sh 

Fazendo um script executável com chmod

Quando executamos o script, os registros são divididos corretamente em seus campos constituintes, com cada campo armazenado em uma variável diferente.

 ./field.sh 

O arquivo CSV analisado pelo script field.sh.

Cada registro é impresso como um conjunto de campos.

Selecionando campos

Talvez não queiramos ou precisemos recuperar todos os campos. Podemos obter uma seleção de campos incorporando o comando cut .

Esse script é chamado de “select.sh”.

 #!/bin/bash

while IFS="," leia -r id jobtitle branch state
Faz
  echo "ID do registro: $id"
  echo "Título do trabalho: $jobtitle"
  echo "Ramo: $ramo"
  echo "Estado: $estado"
  eco ""
feito < <(cut -d "," -f1,4,6,7 sample.csv | tail -n +2)

Adicionamos o comando cut na cláusula de substituição do processo. Estamos usando a opção -d (delimitador) para dizer ao cut para usar vírgulas “ , ” como delimitador. A opção -f (campo) diz ao cut que queremos os campos um, quatro, seis e sete. Esses quatro campos são lidos em quatro variáveis, que são impressas no corpo do loop while .

Isso é o que obtemos quando executamos o script.

 ./select.sh 

Analisando o arquivo CSV com field.sh para extrair uma seleção específica de campos

Ao adicionar o comando cut , podemos selecionar os campos que queremos e ignorar os que não queremos.

Até agora tudo bem. Mas…

Se o CSV com o qual você lida não é complicado, sem vírgulas ou aspas nos dados de campo, o que abordamos provavelmente atenderá às suas necessidades de análise de CSV. Para mostrar os problemas que podemos encontrar, modificamos uma pequena amostra dos dados para ficar assim.

 id,nome,sobrenome,cargo-título,endereço de e-mail,filial,estado
1,Rosalyn,Brennan,"Steward, Senior",[email protected],Minneapolis,Maryland
2,Danny,Redden,"Analista ""Budget""",[email protected],Venice,North Carolina
3, Lexi, Roscoe, Farmacêutico,, Irlington, Vermont
  • O registro um tem uma vírgula no campo job-title , então o campo precisa ser colocado entre aspas.
  • O registro dois tem uma palavra envolta em dois conjuntos de aspas no campo jobs-title .
  • O registro três não tem dados no campo email-address .

Esses dados foram salvos como "sample2.csv". Modifique seu script “field.sh” para chamar o “sample2.csv” e salve-o como “field2.sh”.

 #! /bin/bash

while IFS="," read -r id firstname sobrenome jobtitle email branch state
Faz
  echo "ID do registro: $id"
  echo "Nome: $nome"
  echo "Sobrenome: $sobrenome"
  echo "Título do trabalho: $jobtitle"
  echo "Adicionar email: $email"
  echo "Ramo: $ramo"
  echo "Estado: $estado"
  eco ""
feito < <(cauda -n +2 amostra2.csv)

Quando executamos este script, podemos ver rachaduras aparecendo em nossos analisadores CSV simples.

 ./field2.sh 

Executando o campo2.sh

O primeiro registro divide o campo de cargo em dois campos, tratando a segunda parte como o endereço de e-mail. Cada campo depois disso é deslocado um lugar para a direita. O último campo contém os valores da branch e do state .

Um registro com um campo dividido em dois campos

O segundo registro mantém todas as aspas. Deve ter apenas um único par de aspas ao redor da palavra "Orçamento".

Um registro com aspas mal tratadas

O terceiro registro realmente trata o campo ausente como deveria. O endereço de e-mail está faltando, mas todo o resto está como deveria estar.

Um registro com um campo ausente, que é tratado corretamente

Contraintuitivamente, para um formato de dados simples, é muito difícil escrever um analisador CSV de caso geral robusto. Ferramentas como o awk permitem que você se aproxime, mas sempre há casos extremos e exceções que escapam.

Como usar o comando awk no Linux
RELACIONADO Como usar o comando awk no Linux

Tentar escrever um analisador CSV infalível provavelmente não é o melhor caminho a seguir. Uma abordagem alternativa - especialmente se você estiver trabalhando com algum tipo de prazo - emprega duas estratégias diferentes.

Uma é usar uma ferramenta projetada para manipular e extrair seus dados. A segunda é higienizar seus dados e substituir cenários de problemas, como vírgulas e aspas incorporadas. Seus analisadores Bash simples podem então lidar com o CSV amigável ao Bash.

O kit de ferramentas csvkit

O kit de ferramentas CSV csvkit é uma coleção de utilitários criados expressamente para ajudar a trabalhar com arquivos CSV. Você precisará instalá-lo em seu computador.

Para instalá-lo no Ubuntu, use este comando:

 sudo apt instalar csvkit 

Instalando o csvkit no Ubuntu

Para instalá-lo no Fedora, você precisa digitar:

 sudo dnf install python3-csvkit 

Instalando o csvkit no Fedora

No Manjaro o comando é:

 sudo pacman -S csvkit 

Instalando o csvkit no Manjaro

Se passarmos o nome de um arquivo CSV para ele, o utilitário csvlook exibe uma tabela mostrando o conteúdo de cada campo. O conteúdo do campo é exibido para mostrar o que o conteúdo do campo representa, não como está armazenado no arquivo CSV.

Vamos tentar csvlook com nosso arquivo problemático “sample2.csv”.

 csvlook sample2.csv 

CSV problemático analisado corretamente pelo csvlook

Todos os campos são exibidos corretamente. Isso prova que o problema não é o CSV. O problema é que nossos scripts são muito simplistas para interpretar o CSV corretamente.

Para selecionar colunas específicas, use o comando csvcut . A opção -c (coluna) pode ser usada com nomes de campos ou números de colunas ou uma combinação de ambos.

Suponha que precisamos extrair os nomes e sobrenomes, cargos e endereços de e-mail de cada registro, mas queremos que a ordem dos nomes seja "sobrenome, nome". Tudo o que precisamos fazer é colocar os nomes ou números dos campos na ordem que queremos.

Esses três comandos são todos equivalentes.

 csvcut -c sobrenome, nome, cargo-título, endereço de e-mail amostra2.csv
 csvcut -c sobrenome, nome, 4,5 amostra2.csv
 csvcut -c 3,2,4,5 amostra2.csv 

Selecionando campos em uma ordem preferencial com csvcut

Podemos adicionar o comando csvsort para classificar a saída por um campo. Estamos usando a opção -c (coluna) para especificar a coluna pela qual classificar e a opção -r (reversa) para classificar em ordem decrescente.

 csvcut -c 3,2,4,5 amostra2.csv | csvsort -c 1 -r 

Selecionando campos e classificando-os por uma única coluna

Para deixar a saída mais bonita podemos alimentá-la através csvlook .

 csvcut -c 3,2,4,5 amostra2.csv | csvsort -c 1 -r | csvlook 

Usando csvlook para imprimir a seleção ordenada de campos

Um toque legal é que, mesmo que os registros sejam classificados, a linha de cabeçalho com os nomes dos campos é mantida como a primeira linha. Quando estivermos satisfeitos por termos os dados do jeito que queremos, podemos remover o csvlook da cadeia de comando e criar um novo arquivo CSV redirecionando a saída para um arquivo.

Adicionamos mais dados ao “sample2.file”, removemos o comando csvsort e criamos um novo arquivo chamado “sample3.csv”.

 csvcut -c 3,2,4,5 amostra2.csv > amostra3.csv 

Uma maneira segura de higienizar dados CSV

Se você abrir um arquivo CSV no LibreOffice Calc, cada campo será colocado em uma célula. Você pode usar a função localizar e substituir para procurar vírgulas. Você pode substituí-los por “nada” para que desapareçam, ou por um caractere que não afete a análise do CSV, como um ponto e vírgula “ ; " por exemplo.

Você não verá as aspas nos campos entre aspas. As únicas aspas que você verá são as aspas incorporadas nos dados do campo. Estes são mostrados como aspas simples. Localizar e substituí-los por um único apóstrofo “ ' ” substituirá as aspas duplas no arquivo CSV.

Usando o localizar e substituir do LibreOffice Calc para substituir aspas por apóstrofos

Fazer a localização e substituição em um aplicativo como o LibreOffice Calc significa que você não pode excluir acidentalmente nenhuma das vírgulas separadoras de campo, nem excluir as aspas em torno dos campos entre aspas. Você só alterará os valores de dados dos campos.

Alteramos todas as vírgulas em campos com ponto e vírgula e todas as aspas incorporadas com apóstrofos e salvamos nossas alterações.

O arquivo CSV modificado

Em seguida, criamos um script chamado “field3.sh” para analisar “sample3.csv”.

 #! /bin/bash

while IFS="," leia -r sobrenome primeiro nome e-mail do cargo
Faz
  echo "Sobrenome: $sobrenome"
  echo "Nome: $nome"
  echo "Título do trabalho: $jobtitle"
  echo "Adicionar email: $email"
  eco ""
feito < <(cauda -n +2 amostra3.csv)

Vamos ver o que obtemos quando o executamos.

 ./field3.sh 

Uma seção do CSV analisado corretamente

Nosso analisador simples agora pode lidar com nossos registros anteriormente problemáticos.

Você verá muito CSV

CSV é sem dúvida a coisa mais próxima de uma língua comum para dados de aplicativos. A maioria dos aplicativos que lidam com algum tipo de dados oferece suporte à importação e exportação de CSV. Saber como lidar com o CSV — de maneira realista e prática — o ajudará muito.

RELACIONADO: 9 exemplos de script Bash para você começar no Linux