处理/ etc / passwd文件以列出其home文件夹位于/ home中的所有用户


10

我有一个示例/ etc / passwd文件,如下所示:

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

我正尝试在中列出所有带有主文件夹的用户/home/

我写

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

其中e.txt是我在此处复制的文本。

我知道反斜杠存在一个问题,即转义字符,但是如何解决它,以便可以在命令的一行中列出它们?


11
除了答案的一般建议(也与其间只需一秒来了!):它几乎从来没有有意义的cat和管一样的工具awksed或类似的,因为他们可以给出文件名作为参数。
Philippos

1
猫e.txt | grep主页| 切-d“:” -f 1
Arpit Agarwal

3
由于所有用户的UID为1000,因此可能有些棘手。
StrongBad

1
@ArpitAgarwal grep home e.txt | cut -d ":" -f 1。恭喜您获得了UUOC奖。但是,这不是一个好的解决方案。如果有服务“ homebackups”在以守护程序命名的单独用户下运行,该怎么办?这是一个错误的肯定。
NieDzejkob

2
@Philippos re“将[可以]作为文件名的参数分配给工具并传递给工具几乎是没有意义的” –我通常使用cat > tool此类命令行的变体,因为它可以通过保持从左到右的流程来提高清晰度管道链的输入处理输出。这效率较低,但几乎总是最小左右。这也使得将酌情及有用的运行交互非常明显,当进度条(只更换catpv,如果已安装)。
David Spillett

Answers:


11

您可以如下所示转义正斜杠:

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

另一个技巧是使用复杂的字段分隔符:

awk -F'[:/]' '$7=="home"{ print $1 }' ~/Desktop/e.txt
  • -F'[:/]'-对待两者:/成为字段分隔符

2
我认为注释字段(紧接在主目录之前)允许包含斜杠。

12

您可以使用引号代替/正则表达式,以避免转义/

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

有了awk{if (foo) ... }通常可以简化为公正foo {...}


8

假设e.txt实际上是/etc/passwd,您应该实际使用getent passwd而不是解析文件,因为用户帐户信息可能存储在/etc/nsswitch.confLDAP等指定的多个位置。

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

请注意,print如果条件为真,则隐含该语句。不过,这将打印出整行。这将仅打印用户名:

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

4

对于那些不喜欢awk的人来说,可以选择以下方法:

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

说明:

  • grep -E 允许使用一些扩展的正则表达式功能
  • 该表达式([^:]*:)匹配一列,包括以下“:”分隔符
  • ^([^:]*:){5} 匹配每行的前五列
  • ^([^:]*:){5}/home/ 匹配第六列以'/ home /'开头的每一行
  • cut -d: -f1使用:列分隔符仅选择其输入的第一列

3

您也可以将其index用于固定的字符串匹配,例如,grep -F并使用返回值来确保它匹配字符串的开头

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

或者如果需要正则表达式,则将其作为环境变量传递

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

3

只是为了多样性

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

说明

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

如果您想对/home/找到的位置保持谨慎,请进行更改

perl -F: -lane 'print $F[0] if $F[5] =~ m(^/home/)' e.txt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.