Isto pede o Awk. Como o campo que você deseja verificar é o primeiro campo de cada linha, apenas faça referência a $1
.
awk -F: '! ($1 in seen) {print; seen[$1]}' users.txt
Você pode "jogar golfe" para reduzi-lo consideravelmente:
awk -F: '!a[$1]++' users.txt
A forma mais longa é mais ou menos autoexplicativa; você constrói um array associativo usando cada endereço de email como um índice, sem se preocupar em atribuir um valor. Em seguida, você pode apenas verificar se o endereço de e-mail foi "visto" antes (ou seja, se o array associativo já tem um endereço de e-mail específico como um índice) e imprima a linha inteira, se não.
A forma mais curta está realmente fazendo mais ou menos a mesma coisa, mas requer mais explicações para o código mais curto.
O operador ++
do postfix atua em uma variável após a expressão é avaliada, então voltaremos a isso mais tarde.
No Awk, 0 significa falso e diferente de zero significa verdadeiro. !
é para negação e inverte o valor de verdade.
Aparecendo como fora das chaves, a expressão é interpretada como uma expressão booleana, com uma ação associada (entre chaves) a ser executada se a expressão for verdadeira. Como nenhuma ação é explicitamente declarada, a ação padrão (implícita) de imprimir a linha inteira é usada, se a expressão for avaliada como verdadeira (diferente de zero).
Essencialmente, isso recupera o valor na matriz associativa a
que é apontada como o endereço de e-mail (primeiro campo) como seu índice - ou cria esse valor inicializado como 0 se ainda não estiver presente, interpreta um 0 como falso ou diferente de zero como verdadeiro, inverte esse valor de verdade e imprime toda a linha se o resultado for "verdadeiro" e, em seguida, incrementa o valor armazenado no array associativo nesse ponto.
Uma linguagem Awk bastante comum, na verdade, mas eu não culparia você por usar a versão mais explícita. :)