Traitez le fichier / etc / passwd pour répertorier tous les utilisateurs dont le dossier de départ se trouve dans / home


10

J'ai un exemple de fichier / etc / passwd comme celui-ci:

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

J'essaie de répertorier tous les utilisateurs avec un dossier de départ dans /home/.

J'ai écrit

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

où e.txt est le texte que j'ai copié ici.

Je comprends qu'il y a un problème avec la barre oblique inverse qui est un caractère d'échappement, mais comment puis-je le corriger pour pouvoir les répertorier sur une seule ligne de commande?


11
Un conseil général en plus des réponses (qui viennent avec juste une seconde entre les deux!): Cela n'a presque jamais de sens catet de diriger vers des outils comme awkou sedou similaires, car ils peuvent être donnés le nom de fichier comme argument.
Philippos

1
cat e.txt | accueil grep | cut -d ":" -f 1
Arpit Agarwal

3
Comme tous les utilisateurs ont un UID de 1000, les choses peuvent être un peu délicates.
StrongBad

1
@ArpitAgarwal grep home e.txt | cut -d ":" -f 1. Félicitations pour votre prix UUOC. Cependant, ce n'est pas une bonne solution. Que faire s'il existe un service "homebackups" qui s'exécute sous un utilisateur distinct nommé d'après le démon? C'est un faux positif.
NieDzejkob

2
@Philippos re "Cela n'a presque jamais de sens de diriger et de diriger vers des outils [qui] peuvent recevoir le nom de fichier comme argument" - j'utilise généralement une cat > toolvariante de ces lignes de commande car elle peut améliorer la clarté en maintenant le flux de gauche à droite de l'entrée-traitement-sortie de la chaîne de tuyaux. Il est moins efficace, mais presque toujours de manière minimale. Il est également très évident d'ajouter une barre de progression lorsque cela est pertinent et utile lors de l'exécution interactive (il suffit de le remplacer catpar pvs'il est installé).
David Spillett

Réponses:


11

Vous pouvez échapper aux barres obliques comme indiqué ci-dessous:

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

Une autre astuce serait d'utiliser un séparateur de champ complexe:

awk -F'[:/]' '$7=="home"{ print $1 }' ~/Desktop/e.txt
  • -F'[:/]'- traiter les deux :et /être un séparateur de champs

2
Je crois que le champ de commentaire (juste avant le répertoire personnel) peut contenir une barre oblique.

12

Vous pouvez utiliser des guillemets au lieu de /pour l'expression régulière, pour éviter d'échapper à /:

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

Avec awk, {if (foo) ... }peut souvent être simplement simplifié foo {...}.


8

En supposant que e.txtc'est en fait /etc/passwd, vous devez réellement utiliser getent passwdau lieu d'analyser le fichier car les informations de compte d'utilisateur peuvent être stockées à plusieurs emplacements spécifiés dans /etc/nsswitch.confLDAP.

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

Notez que l' printinstruction est implicite lorsque la condition est vraie. Cela imprimera cependant toute la ligne. Cela n'imprimera que le nom d'utilisateur:

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

4

Alternative pour ceux d'entre nous qui n'aiment tout simplement pas awk:

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

Explication:

  • grep -E permet l'utilisation de quelques fonctionnalités d'expression régulière étendues
  • L'expression ([^:]*:)correspond à une colonne, y compris le séparateur «:» suivant
  • ^([^:]*:){5} correspond aux cinq premières colonnes de chaque ligne
  • ^([^:]*:){5}/home/ correspond à chaque ligne où la 6e colonne commence par '/ home /'
  • cut -d: -f1sélectionne uniquement la première colonne de son entrée, en utilisant :comme séparateur de colonne

3

Vous pouvez également utiliser indexpour une correspondance de chaîne fixe comme grep -Fet utiliser la valeur de retour pour vous assurer qu'elle correspond au début de la chaîne

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

ou si l'expression régulière est nécessaire, passez-la comme variable d'environnement

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

3

Juste pour la variété

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

Explication

-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 si vous voulez être pointilleux sur l'endroit où /home/se trouve

perl -F: -lane 'print $F[0] if $F[5] =~ m(^/home/)' e.txt
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.