Assumindo que o formato de arquivo que você está mostrando é rígido, de modo que um aluno só apareça duas vezes se tiver dois professores diferentes e que as entradas de um determinado aluno estejam sempre próximas uma da outra, use este comando para encontrar todas as duplicatas. As duplicatas neste arquivo denotam que um aluno tem vários professores, portanto, poderíamos ignorar esse fato.
Exemplo
$ awk -F';' '{ print $1 }' file | uniq -d
jdoe
Isso analisa o arquivo file
e o divide usando a opção awk
do separador de campos -F';'
. Em seguida, instruímos awk
a imprimir apenas o primeiro campo, ou seja, os nomes dos alunos. Em seguida, enviamos essa saída para uniq
e informamos para imprimir apenas as linhas duplicadas.
Poderíamos então usar essas informações em um loop for e apenas imprimir as linhas que tiverem um aluno na lista retornada pelo comando acima. Aqui está uma estrutura aproximada do aspecto do ciclo:
$ for i in $(..cmd from above..); do
... print lines that contain "$i" ...
done
Aqui estamos pegando a saída do comando awk
inicial e estamos passando por ele com um loop for no shell Bash. Essa é tipicamente a abordagem que a maioria das pessoas adotará quando começar.
Exemplo
$ for i in $(awk -F';' '{ print $1 }' file | uniq -d); do \
grep "^$i;" file; done
jdoe;ateacher
jdoe;bteacher
Esta abordagem, apesar de funcionar, tem alguns problemas. Se os nomes dos arquivos contiverem espaços, essa abordagem falhará. Você pode alternar para um método mais sofisticado como esse usando um loop while.
$ while read; do grep "^$i;" file; done \
< <(awk -F';' '{ print $1 }' file | uniq -d)
jdoe;ateacher
jdoe;bteacher
Aqui estamos pegando a saída do nosso comando e passando para o loop while assim:
$ while read; do .... ; done < <(...our command...)
Isso tem a vantagem de criar um arquivo temporário com essa notação e passar todos os resultados como linhas para o loop while. Portanto, o comando read
agora só precisa analisar os resultados sendo divididos por uma nova linha, em vez de um espaço na implementação do loop for.
< <(...command...)
Exemplo
Veja o que acontece com o loop e espaços:
$ for i in jdoe john smith jjill;do echo "$i"; done
jdoe
john
smith
jjill