Обробіть / etc / passwd файл, щоб перелічити всіх користувачів, домашня папка яких знаходиться в / home


10

У мене є приклад / etc / passwd-файл, такий:

tom:x:1000:1000:Work:/home/tom:/bin/bash
george:x:1000:1000:Work:/home/george:/bin/bash
bla:x:1000:1000:Work:/home/bla:/bin/bash
boo:x:1000:1000:Work:/home/boo:/bin/bash
bee:x:1000:1000:Work:/root/list:/bin/bash

Я намагаюся перерахувати всіх користувачів, у яких домашня папка /home/.

я написав

cat ~/Desktop/e.txt |awk -F ":" '{if ($6 ~/^/home/) print $1;}'

де e.txt - текст, який я тут скопіював.

Я розумію, що існує проблема із зворотною косою рисою, яка є символом втечі, але як це виправити, щоб перерахувати їх в одному рядку команди?


11
Загальна порада, окрім відповідей (які надходять лише з однією секундою між ними!): Це майже ніколи не має сенсу catта передавати такі інструменти, як awkабо sedподібні, оскільки їм можна надати ім'я файлу як аргумент.
Філіппос

1
кішка, наприклад, | греп додому | cut -d ":" -f 1
Arpit Agarwal

3
Оскільки у всіх користувачів UID з 1000 речей, може бути трохи хитро.
StrongBad

1
@ArpitAgarwal grep home e.txt | cut -d ":" -f 1. Вітаємо вас з нагородою UUOC. Однак це не гарне рішення. Що робити, якщо є сервіс "homebackups", який працює під окремим користувачем, названим на честь демона? Це хибний позитив.
NieDzejkob

2
@Philippos re "Це майже ніколи не має сенсу котувати і передавати інструменти [що] можна надати ім'я файлу як аргумент" - я зазвичай використовую cat > toolваріант таких командних рядків, оскільки це може покращити чіткість, підтримуючи потік зліва направо. вводу-обробки-виходу ланцюга труб. Це є менш ефективним, але майже завжди мінімально так. Він також робить додавання прогрес бар , де ставлення і корисно при роботі в інтерактивному режимі дуже очевидно (просто замінити catз , pvякщо він встановлений).
Девід Спіллетт

Відповіді:


11

Ви можете уникнути нахилів вперед, як показано нижче:

awk -F':' '$6~/^\/home\//{ print $1 }' ~/Desktop/e.txt

Ще одна хитрість - використання складного роздільника поля:

awk -F'[:/]' '$7=="home"{ print $1 }' ~/Desktop/e.txt
  • -F'[:/]'- ставитись до обох :та /бути роздільником поля

2
Я вважаю, що поле коментаря (безпосередньо перед домашнім каталогом) може містити косу рису.

12

Ви можете використовувати лапки замість /регулярного виразу, щоб не уникнути /:

awk -F: '$6 ~ "^/home/" {print $1}' ~/Desktop/e.txt

З awk, {if (foo) ... }часто можна спростити просто foo {...}.


8

Якщо припустити , що ви e.txtнасправді /etc/passwd, вам слід використовувати getent passwdзамість розбору файлу, оскільки інформація облікового запису користувача може зберігатися в декількох місцях, зазначених у /etc/nsswitch.confLDAP.

getent passwd | awk -F ':' '$6 ~ "^/home"'

Зауважте, що printтвердження мається на увазі, коли умова справжня. Однак це надрукує всю лінійку Це буде друкувати тільки ім'я користувача:

getent passwd | awk -F ':' '$6 ~ "^/home" {print $1}'

4

Альтернатива для тих із нас, хто просто не любить awk:

grep -E '^([^:]*:){5}/home/' ~/Desktop/e.txt | cut -d: -f1

Пояснення:

  • grep -E дозволяє використовувати кілька розширених функцій регулярного вираження
  • Вираз ([^:]*:)відповідає одному стовпцю, включаючи такий роздільник ':'
  • ^([^:]*:){5} відповідає першим п'яти стовпцям кожного рядка
  • ^([^:]*:){5}/home/ відповідає кожному рядку, де 6-й стовпець починається з '/ home /'
  • cut -d: -f1вибирає лише перший стовпець свого вводу, використовуючи :як роздільник стовпців

3

Ви також можете використовувати indexдля фіксованого рядка відповідність, як, grep -Fі використовувати повернене значення, щоб переконатися, що воно відповідає початку рядка

$ awk -F: 'index($6,"/home/")==1{print $1}' ip.txt
tom
george
bla
boo

або якщо потрібен регулярний вираз, передайте його як змінну середовища

$ r='^/home/' awk -F: '$6 ~ ENVIRON["r"]{print $1}' ip.txt
tom
george
bla
boo

3

Просто для різноманітності

$ perl -F: -lane 'print $F[0] if m(/home/)' e.txt
tom
george
bla
boo

Пояснення

-F:     use ":" as field separator  
-lane
    l   add newline line-ending to every print statement
    a   auto-split input lines into @F array
    n   apply expression line by line to named file (or STDIN)
    e   evaluate perl commands given on command line

print $F[0]   print (only) the first field of each line
if m(/home/)  but only if the line contains the text /home/

Варіант, якщо ви хочете бути прискіпливими щодо того, де /home/його знайти

perl -F: -lane 'print $F[0] if $F[5] =~ m(^/home/)' e.txt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.