Procese el archivo / etc / passwd para enumerar todos los usuarios cuya carpeta de inicio se encuentra en / home

10

Tengo un ejemplo de archivo / etc / passwd como este:

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

Estoy tratando de enumerar todos los usuarios con una carpeta de inicio /home/.

escribí

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

donde e.txt es el texto que copié aquí.

Entiendo que hay un problema con la barra diagonal inversa que es un carácter de escape, pero ¿cómo lo soluciono para poder enumerarlos en una línea de un comando?

erans
fuente
11
Un consejo general además de las respuestas (¡que vienen con solo un segundo en el medio!): Casi nunca tiene sentido caty canalizar herramientas como awko sedsimilares, ya que se les puede dar el nombre de archivo como argumento.
Philippos
1
gato e.txt | grep inicio | cut -d ":" -f 1
Arpit Agarwal
3
Como todos los usuarios tienen un UID de 1000 cosas, puede ser un poco complicado.
StrongBad
1
@ArpitAgarwal grep home e.txt | cut -d ":" -f 1. Felicitaciones por su premio UUOC. Sin embargo, esta no es una buena solución. ¿Qué pasa si hay un servicio de "homebackups" que se ejecuta bajo un usuario separado llamado así por el demonio? Eso es un falso positivo.
NieDzejkob
2
@Philippos re "Casi nunca tiene sentido para cat y pipe a herramientas [que] se le puede dar el nombre de archivo como argumento" - Generalmente uso cat > toolvariante de tales líneas de comando porque puede mejorar la claridad al mantener el flujo de izquierda a derecha de la entrada-procesamiento-salida de la cadena de tuberías. Que es menos eficiente, pero casi siempre de manera mínimamente. También hace que añadir una barra de progreso cuando sea pertinente y útil cuando se ejecuta de forma interactiva muy evidente (basta con sustituir catcon pvsi está instalado).
David Spillett

Respuestas:

11

Puede escapar de las barras diagonales como se muestra a continuación:

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

Otro truco sería usar un separador de campo complejo:

awk -F'[:/]' '$7=="home"{ print $1 }' ~/Desktop/e.txt
  • -F'[:/]'- tratar a ambos :y /ser un separador de campo
RomanPerekhrest
fuente
2
Creo que el campo de comentarios (inmediatamente antes del directorio de inicio) puede contener una barra diagonal.
12

Puede usar comillas en lugar de /para la expresión regular, para evitar escapar de /:

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

Con awk, a {if (foo) ... }menudo se puede simplificar a solo foo {...}.

muru
fuente
8

Suponiendo que e.txtes realmente /etc/passwd, debería usarlo en getent passwdlugar de analizar el archivo, ya que la información de la cuenta de usuario puede almacenarse en múltiples ubicaciones especificadas /etc/nsswitch.conf, como LDAP.

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

Tenga en cuenta que la printdeclaración está implícita cuando la condición es verdadera. Sin embargo, eso imprimirá toda la línea. Esto imprimirá solo el nombre de usuario:

getent passwd | awk -F ':' '$6 ~ "^/home" {print $1}'
Pausado hasta nuevo aviso.
fuente
4

Alternativa para aquellos de nosotros que simplemente no nos gusta awk:

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

Explicación:

  • grep -E permite el uso de algunas características extendidas de expresión regular
  • La expresión ([^:]*:)coincide con una columna, incluido el siguiente separador ':'
  • ^([^:]*:){5} coincide con las primeras cinco columnas de cada línea
  • ^([^:]*:){5}/home/ coincide con cada línea donde la sexta columna comienza con '/ home /'
  • cut -d: -f1selecciona solo la primera columna de su entrada, utilizando :como separador de columna
rosarote elfe
fuente
3

También puede usar indexuna coincidencia de cadena fija como grep -Fy usar el valor de retorno para asegurarse de que coincida con el inicio de la cadena

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

o si se necesita regex, páselo como variable de entorno

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

Solo por variedad

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

Explicación

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

Variación si quieres ser exigente sobre dónde /home/se encuentra

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