Processe o arquivo / etc / passwd para listar todos os usuários cuja pasta home está em / home

9

Eu tenho um exemplo de arquivo / etc / passwd assim:

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

Estou tentando listar todos os usuários com uma pasta pessoal em /home/ .

eu escrevi

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

em que e.txt é o texto que copiei aqui.

Eu entendo que há um problema com a barra invertida que é um caractere de escape, mas como posso corrigi-lo para que eu possa listá-lo em uma linha de comando?

    
por erans 07.11.2017 / 10:17

6 respostas

10

Você pode escapar de barras como mostrado abaixo:

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

Outro truque seria usar um separador de campo complexo:

awk -F'[:/]' '$7=="home"{ print $1 }' ~/Desktop/e.txt
  • -F'[:/]' - trata os campos : e / como separador de campos
por 07.11.2017 / 10:26
11

Você pode usar aspas em vez de / para o regex, para evitar o escape do / :

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

Com awk , {if (foo) ... } geralmente pode ser simplificado para apenas foo {...} .

    
por 07.11.2017 / 10:26
7

Supondo que e.txt seja realmente /etc/passwd , você deve usar getent passwd em vez de analisar o arquivo, pois as informações da conta do usuário podem ser armazenadas em vários locais especificados em /etc/nsswitch.conf , como LDAP.

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

Observe que a instrução print está implícita quando a condição é verdadeira. Isso vai imprimir toda a linha, no entanto. Isso imprimirá apenas o nome do usuário:

getent passwd | awk -F ':' '$6 ~ "^/home" {print $1}'
    
por 07.11.2017 / 20:00
4

Alternativa para aqueles que não gostam do awk:

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

Explicação:

  • grep -E permite o uso de alguns recursos estendidos de expressão regular
  • A expressão ([^:]*:) corresponde a uma coluna, incluindo o seguinte separador ':'
  • ^([^:]*:){5} corresponde às cinco primeiras colunas de cada linha
  • ^([^:]*:){5}/home/ corresponde a todas as linhas em que a sexta coluna começa com '/ home /'
  • cut -d: -f1 seleciona apenas a primeira coluna de sua entrada, usando : como separador de coluna
por 07.11.2017 / 15:52
3

Você também pode usar index para correspondência de sequência fixa como grep -F e usar o valor de retorno para garantir que corresponda ao início da sequência de caracteres

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

ou se regex for necessário, passe-o como variável de ambiente

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

Apenas por variedade

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

Explicação

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

Variação se você quiser ser exigente sobre onde /home/ é encontrado

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