Как уже отмечали другие, grepэто не лучший инструмент для этого. Если вы настаиваете на его использовании, и если вы grepподдерживаете -o(печатать только совпадающую часть строки) и -P(используйте регулярные выражения, совместимые с Perl), вы можете сделать это:
$ grep -oP '^[^:]+|.*:\K[^:]+(?=:[^:]+)' /etc/password
terdon
/home/terdon
bob
/home/bob
Обратите внимание, что это будет печатать всех пользователей, включая пользователей системы. Я показываю только 4 строки в качестве примера.
Это напечатает имя пользователя и домашние каталоги всех пользователей, но в отдельных строках. Затем вам нужно объединить каждую пару строк, чтобы собрать их вместе:
$ 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
объяснение
Регулярное выражение состоит из двух частей, оно ищет ^[^:]+OR (вот что |значит) .*:\K[^:]+(?=:[^:]+). Первый ищет один или несколько не :символов из начала строки. Это соответствует имени пользователя. Вторая часть ищет как можно больше символов до a :( .*:), а затем отбрасывает их (вот что \Kделает), чтобы они не печатались. Затем он соответствует строке non-, за :которой следует :и non- :. (?=foo)Конструкция называется положительным опережением и способ сопоставления символов после шаблона , не включая эти символы в самой игре.
Команда perlзаменит символы новой строки на :и пробелы, если номер текущей строки $.делится на 2. Итак, каждая вторая строка.
/etc/passwdможет или не может быть, где все пользователи. Учтите такжеgetent passwd.