Verarbeiten Sie die Datei / etc / passwd, um alle Benutzer aufzulisten, deren Home-Ordner sich in / home befindet

10

Ich habe eine Beispieldatei / etc / passwd wie folgt:

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

Ich versuche, alle Benutzer mit einem Home-Ordner aufzulisten /home/.

Ich hab geschrieben

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

Dabei ist e.txt der Text, den ich hier kopiert habe.

Ich verstehe, dass es ein Problem mit dem Backslash gibt, bei dem es sich um ein Escape-Zeichen handelt, aber wie behebe ich es, damit ich sie in einer Befehlszeile auflisten kann?

erans
quelle
11
Ein allgemeiner Rat neben den Antworten (die mit nur einer Sekunde dazwischen kommen!): Es macht fast nie Sinn cat, Werkzeuge wie awkoder sedoder ähnliches zu verwenden und weiterzuleiten , da ihnen der Dateiname als Argument gegeben werden kann.
Philippos
1
cat e.txt | grep home | cut -d ":" -f 1
Arpit Agarwal
3
Da alle Benutzer eine UID von 1000 haben, können die Dinge etwas schwierig sein.
StrongBad
1
@ArpitAgarwal grep home e.txt | cut -d ":" -f 1. Herzlichen Glückwunsch zu Ihrer UUOC-Auszeichnung. Dies ist jedoch keine gute Lösung. Was ist, wenn es einen Dienst "Homebackups" gibt, der unter einem separaten Benutzer ausgeführt wird, der nach dem Dämon benannt ist? Das ist falsch positiv.
NieDzejkob
2
@Philippos re "Es ist fast nie sinnvoll, Werkzeuge zu [und] zu leiten, denen der Dateiname als Argument zugewiesen werden kann" - Ich verwende im Allgemeinen eine cat > toolVariante solcher Befehlszeilen, da dies die Klarheit verbessern kann, indem der Fluss von links nach rechts beibehalten wird der Eingabe-Verarbeitung-Ausgabe der Rohrkette. Es ist weniger effizient, aber fast immer minimal. Es macht auch das Hinzufügen einen Fortschrittsbalken , wo relevant und nützlich , wenn interaktiv sehr offensichtlich läuft (nur ersetzen catmit , pvwenn diese installiert ist).
David Spillett

Antworten:

11

Sie können Schrägstrichen wie unten gezeigt entkommen:

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

Ein weiterer Trick wäre die Verwendung eines komplexen Feldtrennzeichens:

awk -F'[:/]' '$7=="home"{ print $1 }' ~/Desktop/e.txt
  • -F'[:/]'- beides behandeln :und /ein Feldtrenner sein
RomanPerekhrest
quelle
2
Ich glaube, das Kommentarfeld (unmittelbar vor dem Home-Verzeichnis) darf einen Schrägstrich enthalten.
12

Sie können Anführungszeichen anstelle des /regulären Ausdrucks verwenden, um zu vermeiden, dass /:

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

Mit awk, {if (foo) ... }kann oft nur noch vereinfacht werden foo {...}.

muru
quelle
8

Unter der Annahme , e.txtist eigentlich /etc/passwdsollten Sie tatsächlich nutzen , getent passwdanstatt die Datei zu parsen , da in bestimmten Benutzerkontoinformationen in mehreren Orten gespeichert werden /etc/nsswitch.confals LDAP so.

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

Beachten Sie, dass die printAnweisung impliziert ist, wenn die Bedingung erfüllt ist. Dadurch wird jedoch die gesamte Zeile gedruckt. Dies gibt nur den Benutzernamen aus:

getent passwd | awk -F ':' '$6 ~ "^/home" {print $1}'
Bis auf weiteres angehalten.
quelle
4

Alternative für diejenigen von uns, die awk einfach nicht mögen:

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

Erläuterung:

  • grep -E ermöglicht die Verwendung einiger erweiterter Funktionen für reguläre Ausdrücke
  • Der Ausdruck ([^:]*:)entspricht einer Spalte, einschließlich des folgenden Trennzeichens ':'
  • ^([^:]*:){5} stimmt mit den ersten fünf Spalten jeder Zeile überein
  • ^([^:]*:){5}/home/ stimmt mit jeder Zeile überein, in der die 6. Spalte mit '/ home /' beginnt.
  • cut -d: -f1Wählt nur die erste Spalte seiner Eingabe aus und verwendet sie :als Spaltentrennzeichen
Rosarote Elfe
quelle
3

Sie können auch eine indexfeste Zeichenfolgenübereinstimmung wie verwenden grep -Fund den Rückgabewert verwenden, um sicherzustellen, dass er mit dem Zeichenfolgenanfang übereinstimmt

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

oder wenn Regex benötigt wird, übergeben Sie es als Umgebungsvariable

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

Nur für Abwechslung

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

Erläuterung

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

Variation, wenn Sie wählerisch sein möchten, wo sich etwas /home/befindet

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