Eu tenho um grande arquivo csv (Test.csv), que se parece com isto:
1,2,3,A,5
1,2,3,B,5
1,2,3,E,5
1,2,3,D,5
1,2,3,Z,5
1,2,3,B,5
Quero imprimir as linhas em que a 4ª coluna tem o mesmo conteúdo em arquivos diferentes. Na verdade, preciso juntar essas linhas que possuem o mesmo conteúdo em um novo arquivo csv ou txt, denominado conteúdo da 4ª coluna. Por exemplo:
Saída:
Arquivo A
1,2,3,A,5
1,2,3,A,5
1,2,3,A,5
Arquivo B
1,2,3,B,5
1,2,3,B,5
Como o arquivo de entrada é grande, não tenho ideia de quantos padrões diferentes existem nesta quarta coluna. A coluna 4 contém apenas palavras e as outras colunas contêm palavras e/ou números.
Como não tenho experiência, pesquisei questões semelhantes e até tentei o seguinte código:
awk 'NR==FNR{a[$4]=NR; next} $NF in a {print > "outfile" a[$NF]}' Test.csv
mas nada funcionou. Alguém pode me ajudar por favor? Desde já, obrigado.
Responder1
Isso funcionará de forma eficiente usando classificação POSIX e qualquer awk em qualquer shell em cada caixa UNIX:
$ sort -t, -k4,4 test.csv |
awk -F, '$4!=prev{close(out); out="File"$4; prev=$4} {print > out}'
$ head -n 20 File*
==> FileA <==
1,2,3,A,5
==> FileB <==
1,2,3,B,5
1,2,3,B,5
==> FileD <==
1,2,3,D,5
==> FileE <==
1,2,3,E,5
==> FileZ <==
1,2,3,Z,5
Algumas coisas a serem observadas:
- alguns awks precisam colocar parênteses em torno de uma expressão no lado direito do redirecionamento de saída, e
- alguns awks falham se você não fechar os arquivos de saída conforme eles avançam e, assim, tentar reter muitos arquivos abertos depois de passarem de uma dúzia de arquivos de saída, e
- manter vários arquivos de saída abertos é muito ineficiente em todos os awks que permitem isso, e
- fechar os arquivos de saída linha por linha para compensar isso será muito ineficiente em todos os awks.
Responder2
Você deve poder usar apenas o campo no nome do arquivo de saída. Uma solução simples:
awk -F, '{print > ("file_" $4 ".csv")}' Test.csv
Isso funciona pelo menos no GNU awk e cria file_A.csv, file_B.csvetc. Observe que isso mantém todos os arquivos de saída abertos e fica mais lento quanto mais houver, especialmente se você atingir o limite de arquivos abertos por processo.
-F,define o separador de campos como vírgula.
Não tenho certeza do que o script que você mostrou deve fazer.
Responder3
Algo assim:
$ awk -F, '{ print $0 >> "file-" $4 ".txt"; }' ./tmp.txt
Assim como a resposta de @ilkkachu menciona, flag -Fserve para alterar o separador de campo do padrão, caracteres de espaço em branco, para uma vírgula. Você deve usar
>>em vez de >
para não sobrescrever o arquivo, se ele existir.
Responder4
Pitão
#!/usr/bin/python
uni=[]
k=open('file.txt','r')
for i in k:
g=i.split(",")[3].strip()
if g not in uni:
uni.append(g)
for m in uni:
f=open("{0}.txt".format(m),'w')
l=open('file.txt','r')
for d in l:
if m in d.split(",")[3].strip():
f.write(d)
Já é a melhor solução fornecida no awk, é apenas minha tentativa
for i in `awk -F "," '{if(!seen[$4]++)print $4}' file.txt`; do awk -v i="$i" -F "," '$4==i{print $0}' file.txt >$i.txt; done


