Como dividir um arquivo de acordo com uma coluna (incluindo o cabeçalho) e renomear os arquivos gerados?

7

Eu tenho um .txt que pode ser exemplificado assim:

NAME | CODE
name1 | 001
name2 | 001
name3 | 002
name4 | 003
name5 | 003
name6 | 003

Eu preciso escrever um script para dividir esse arquivo de acordo com a coluna CODE , então, nesse caso, eu recebo isto:

file 1:
NAME | CODE
name1 | 001
name2 | 001

file 2:
NAME | CODE
name3 | 002

file 3:
NAME | CODE
name4 | 003
name5 | 003
name6 | 003

De acordo com algumas pesquisas, usar o awk funcionaria:

$ awk -F, '{print > $2".txt"}' inputfile

O problema é que também preciso incluir o cabeçalho na primeira linha e preciso que os nomes dos arquivos sejam diferentes. Em vez de 001.txt , por exemplo, preciso que o nome do arquivo seja algo como FILE_$FILENAME_IDK.txt .

    
por Geralt 30.10.2015 / 00:29

2 respostas

8

Você poderia tentar assim:

awk 'NR==1{h=$0; next}
!seen[$3]++{f="FILE_"FILENAME"_"$3".txt";print h > f} 
{print >> f}' infile

O item acima salva o cabeçalho em uma variável h ( NR==1{h=$0; next} ) e, se $3 não for visto ( !seen[$3]++ , por exemplo, se for a primeira vez que encontrar o valor atual de $3 ), define nome_do_arquivo ( f=...) e escreve o cabeçalho em nome_do_arquivo ( print h > f ). Em seguida, ele anexa a linha inteira ao nome_do_arquivo ( print >> f Ele usa o padrão FS (separador de campo): branco Se você quiser usar | como FS (ou até mesmo uma regex com gnu awk ) veja cas 'comentário abaixo.

    
por 30.10.2015 / 01:37
1

Aposto que alguém vai inventar um one-liner, mas eu tive que fazer um script:

in='inputfile'
header=$(head -n1 "$in")
codes=($(sed -n 's/.*| \([0-9]\+\)//p' "$in" | uniq ))
for line in "${codes[@]}"; do
    out="file_$i.txt"
    echo "$header" > "$out"
    grep "|.* $line$" "$in" >> "$out"
done
    
por 30.10.2015 / 01:19