Memproses / etc / passwd file untuk mendaftar semua pengguna yang folder rumahnya ada di / home

10

Saya punya contoh file / etc / passwd seperti ini:

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

Saya mencoba mendaftar semua pengguna dengan folder rumah di /home/.

saya menulis

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

di mana e.txt adalah teks yang saya salin di sini.

Saya mengerti ada masalah dengan backslash yang merupakan karakter pelarian, tetapi bagaimana cara memperbaikinya sehingga saya dapat mendaftarnya dalam satu baris perintah?

erans
sumber
11
Saran umum di samping jawaban (yang datang dengan hanya satu detik di antara!): Hampir tidak masuk akal catdan pipa ke alat suka awkatau sedatau sejenisnya, karena mereka dapat diberi nama file sebagai argumen.
Philippos
1
cat e.txt | grep rumah | cut -d ":" -f 1
Arpit Agarwal
3
Karena semua pengguna memiliki UID 1000 hal mungkin sedikit rumit.
StrongBad
1
@ArpitAgarwal grep home e.txt | cut -d ":" -f 1. Selamat atas penghargaan UUOC Anda. Namun, ini bukan solusi yang baik. Bagaimana jika ada layanan "homebackups" yang berjalan di bawah pengguna terpisah yang dinamai daemon? Itu positif palsu.
NieDzejkob
2
@Philippos re "Hampir tidak masuk akal untuk menggunakan cat dan pipe ke alat [yang] dapat diberi nama file sebagai argumen" - Saya biasanya menggunakan cat > toolvarian dari baris perintah seperti itu karena dapat meningkatkan kejelasan dengan mempertahankan aliran kiri ke kanan dari input-pemrosesan-output dari rantai pipa. Ini adalah kurang efisien, tapi hampir selalu minimal jadi. Itu juga membuat menambahkan bilah kemajuan di mana relevan & berguna saat menjalankan secara interaktif sangat jelas (hanya ganti catdengan pvjika itu diinstal).
David Spillett

Jawaban:

11

Anda dapat menghindari garis miring ke depan seperti yang ditunjukkan di bawah ini:

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

Trik lain akan menggunakan pemisah bidang kompleks:

awk -F'[:/]' '$7=="home"{ print $1 }' ~/Desktop/e.txt
  • -F'[:/]'- memperlakukan keduanya :dan /menjadi pemisah lapangan
RomanPerekhrest
sumber
2
Saya percaya bidang komentar (tepat sebelum direktori home) diizinkan berisi garis miring.
12

Anda dapat menggunakan kutipan alih-alih /untuk regex, untuk menghindari lolos dari /:

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

Dengan awk, {if (foo) ... }seringkali bisa disederhanakan menjadi adil foo {...}.

muru
sumber
8

Dengan asumsi e.txtsebenarnya /etc/passwd, Anda harus benar-benar menggunakan getent passwddaripada mem-parsing file karena informasi akun pengguna dapat disimpan di beberapa lokasi yang ditentukan dalam /etc/nsswitch.confseperti LDAP.

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

Perhatikan bahwa printpernyataan itu tersirat ketika kondisinya benar. Itu akan mencetak seluruh baris. Ini hanya akan mencetak nama pengguna:

getent passwd | awk -F ':' '$6 ~ "^/home" {print $1}'
Dijeda sampai pemberitahuan lebih lanjut.
sumber
4

Alternatif bagi kita yang tidak suka awk:

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

Penjelasan:

  • grep -E memungkinkan penggunaan beberapa fitur ekspresi reguler yang diperluas
  • Ekspresi ([^:]*:)cocok dengan satu kolom, termasuk pemisah ':' berikut
  • ^([^:]*:){5} cocok dengan lima kolom pertama dari setiap baris
  • ^([^:]*:){5}/home/ cocok dengan setiap baris di mana kolom ke-6 dimulai dengan '/ home /'
  • cut -d: -f1hanya memilih kolom pertama dari inputnya, menggunakan :sebagai pemisah kolom
peri rosarote
sumber
3

Anda juga dapat menggunakan indexuntuk pencocokan string tetap seperti grep -Fdan menggunakan nilai kembali untuk memastikan itu cocok dengan awal string

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

atau jika diperlukan regex, berikan sebagai variabel lingkungan

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

Hanya untuk variasi

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

Penjelasan

-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/

Variasi jika Anda ingin pilih-pilih di mana /home/ditemukan

perl -F: -lane 'print $F[0] if $F[5] =~ m(^/home/)' e.txt
RedGrittyBrick
sumber