Como outros já apontaram, grepnão é a melhor ferramenta para isso. Se você insistir em usá-lo, e se você grepsuporta -o(imprima apenas a parte correspondente da linha) e -P(use Expressões Regulares Compatíveis com Perl), faça o seguinte:
$ grep -oP '^[^:]+|.*:\K[^:]+(?=:[^:]+)' /etc/password
terdon
/home/terdon
bob
/home/bob
Observe que isso imprimirá todos os usuários, incluindo os usuários do sistema. Estou apenas mostrando 4 linhas como exemplo.
Isso imprimirá o nome do usuário e os diretórios pessoais de todos os usuários, mas em linhas separadas. Você precisa unir cada par de linhas para juntá-las:
$ grep -oP '^[^:]+|.*:\K[^:]+(?=:[^:]+)' /etc/passwd | perl -pe 's/\n/ : / if $.%2'
root : /root
bin : /bin
daemon : /
mail : /var/spool/mail
ftp : /srv/ftp
http : /srv/http
uuidd : /
dbus : /
nobody : /
systemd-journal-gateway : /
systemd-timesync : /
systemd-network : /
systemd-bus-proxy : /
systemd-resolve : /
systemd-journal-upload : /
systemd-coredump : /
systemd-journal-remote : /
terdon : /home/terdon
avahi : /
polkitd : /
colord : /var/lib/colord
rtkit : /proc
gdm : /var/lib/gdm
git : /
bob : /home/bob
Explicação
O regex tem duas partes: procura ^[^:]+OR (é isso que |significa) .*:\K[^:]+(?=:[^:]+). O primeiro procura por um ou mais não :caracteres desde o início da linha. Isso corresponde ao nome do usuário. A segunda parte procura o máximo de caracteres possível até a :( .*:) e os descarta (é o que \Kfaz) para que não sejam impressos. Em seguida, corresponde a uma sequência de não - :que é seguida por :e não - :. A (?=foo)construção é chamada de aparência positiva e é uma maneira de corresponder os caracteres após um padrão sem incluir esses caracteres na própria correspondência.
O perlcomando substituirá as novas linhas por :e espaços se o número da linha atual ( $.) for divisível por 2. Portanto, a cada segunda linha.
/etc/passwdpode ou não estar onde estão todos os usuários. Considere tambémgetent passwd.