![Мне нужно найти все домашние каталоги пользователей, перечисленные с помощью grep из /etc/passwd](https://rvso.com/image/89172/%D0%9C%D0%BD%D0%B5%20%D0%BD%D1%83%D0%B6%D0%BD%D0%BE%20%D0%BD%D0%B0%D0%B9%D1%82%D0%B8%20%D0%B2%D1%81%D0%B5%20%D0%B4%D0%BE%D0%BC%D0%B0%D1%88%D0%BD%D0%B8%D0%B5%20%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D0%B8%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9%2C%20%D0%BF%D0%B5%D1%80%D0%B5%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5%20%D1%81%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E%20grep%20%D0%B8%D0%B7%20%2Fetc%2Fpasswd.png)
У меня есть вопрос, похожий на другой на этом сайте, где человек должен был найти список всех пользователей, использующих grep или awk из /etc/passwd. Это сработало для меня, но я пытался перевести это, чтобы найти и перечислить их домашние каталоги также. Я уже знаю, что вы не можете сделать это в одну строку, поэтому я знаю, что я бы использовал конвейер. Я провел свое исследование в Интернете, но я не могу понять, в чем проблема. Если я использую grep и делаю что-то вроде следующего:
grep -oE '^[/*/]$' /etc/passwd
...вероятно, это выдаст мне ошибку или также покажет мне файлы /bin/bash, что мне не нужно. Мне просто нужны имена пользователей и их домашние каталоги, перечисленные с помощью grep! Я также не уверен, покажет ли * другие прямые слеши как символы, так как некоторые домашние каталоги имеют больше, чем просто два / (прямых слеша).
решение1
Вы можете использоватьcut
для разделения файлов со столбцами по определенному разделителю:
cut -d: -f6 /etc/passwd
Или -f1,6
для столбцов (полей) 1 и 6.
решение2
Grep на самом деле не является инструментом для парсинга данных таким образом; grep больше подходит для сопоставления с шаблоном, а вы пытаетесь выполнить обработку текста. Вам следует использовать awk.
awk -F":" '$7 == "/bin/false" {print "User: "$1 "Home Dir: "$6}' /etc/passwd
awk
- Команда-F":"
– Устанавливает разделитель данных на:
$7 == "/bin/false"
– Проверяет, является ли 7-й столбец данных/bin/false
{print "User: "$1 "Home Dir: "$6}'
– Предлагает напечатать первый и шестой столбцы в указанном формате./etc/passwd
– Файл, который мы обрабатываем?
решение3
Как уже указывали другие, 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[^:]+(?=:[^:]+)
. Первая часть ищет один или несколько не- :
символов с начала строки. Это соответствует имени пользователя. Вторая часть ищет как можно больше символов до :
( .*:
), а затем отбрасывает их (именно это делает \K
), чтобы они не выводились. Затем оно сопоставляет строку не- , :
за которой следует :
и не- :
. (?=foo)
Конструкция называетсяпозитивный взгляд впереди это способ сопоставления персонажейпослешаблон без включения этих символов в само совпадение.
Команда perl
заменит символы новой строки на :
пробелы, если номер текущей строки ( $.
) делится на 2. То есть, каждая вторая строка.
решение4
Я считаю, что это можно сделать с помощью «cut», используя только один двоичный файл, избегая конвейеров и достигая тех же результатов, что и другие ответы, но более элегантным способом :), например так:
$ cut -d : -f 1,6 /etc/passwd
root:/root
daemon:/usr/sbin
bin:/bin
sys:/dev
sync:/bin
games:/usr/games
man:/var/cache/man
lp:/var/spool/lpd
mail:/var/mail
news:/var/spool/news
....
Если вы хотите получить вывод, лучше отформатированный + в алфавитном порядке, вот он, но компромисс в том, что вам придется использовать больше двоичных файлов:
$ cut -d : -f 1,6 /etc/passwd | sort | column
avahi-autoipd:/var/lib/avahi-autoipd man:/var/cache/man
avahi:/var/run/avahi-daemon messagebus:/var/run/dbus
backup:/var/backups news:/var/spool/news
bin:/bin nobody:/nonexistent
clickpkg:/nonexistent ntp:/home/ntp
colord:/var/lib/colord proxy:/bin
daemon:/usr/sbin pulse:/var/run/pulse
dnsmasq:/var/lib/misc root:/root
games:/usr/games rtkit:/proc
gnats:/var/lib/gnats saned:/home/saned
hplip:/var/run/hplip speech-dispatcher:/var/run/speech-dispatcher
irc:/var/run/ircd sync:/bin
ivanleon:/home/ivanleon sys:/dev
kernoops:/ syslog:/home/syslog
libuuid:/var/lib/libuuid usbmux:/home/usbmux
lightdm:/var/lib/lightdm usermetrics:/var/lib/usermetrics
list:/var/list uucp:/var/spool/uucp
lp:/var/spool/lpd whoopsie:/nonexistent
lxc-dnsmasq:/var/lib/lxc www-data:/var/www
mail:/var/mail