Linux中使用正则表达式打印特定字段

Linux中使用正则表达式打印特定字段

我正在尝试从名为 的文件中打印第四个字段值为 1001 或 1003 的行mypasswd。我只能将 grep 或egrep 与正则表达式一起使用。这是文件:

daemon:x:2:2:Daemon 1001:/sbin:/bin/bash
ftp:x:40:49:FTP export account:/srv/ftp:/bin/bash
daemonuser:x:50:59:nouser/bin/false:/home/nouser:/bin/bash
gdm:x:106:111:Gnome Display Mgr daemon:/var/lib/gdm:/bin/false
haldaemon:x:101:102:User for haldaemon:/var/run/hald:/bin/false
lp:x:4:7:Printing daemon:/var/spool/lpd:/bin/bash
mail:x:8:12:Mailer daemon:/var/spool/clientmqueue:/bin/false
root:x:0:0:root:/root:/bin/bash
sshd:x:71:65:SSH daemon:/var/lib/sshd:/bin/false
olivert:x:1001:1005:Tom Oliver:/home/olivert:/bin/csh
smiths:x:1049:1000:Sue Williams:/export/home/smiths:/bin/csh
northj:x:1003:1003:Jim jones-North:/home/northj:/bin/csh
denniss:x:1005:1003:Sue Dennis:/home/denniss:/bin/bash
smitha:x:1050:1001:Amy Smith:/export/home/smitha:/bin/bash
jonesc:x:1053:1001:Cathy Jones:/export/home/jonesc:/bin/ksh
smithd:x:1055:1001:Dan Smith Jr:/export/home/smithd:/bin/csh

所以输出应该是

northj:x:1003:1003:Jim jones-North:/home/northj:/bin/csh
denniss:x:1005:1003:Sue Dennis:/home/denniss:/bin/bash
smitha:x:1050:1001:Amy Smith:/export/home/smitha:/bin/bash
jonesc:x:1053:1001:Cathy Jones:/export/home/jonesc:/bin/ksh
smithd:x:1055:1001:Dan Smith Jr:/export/home/smithd:/bin/csh

我可以轻松地运行egrep '1001|1003' mypasswd,但这也给了我“daemon”(第五个字段包含“1001”)和“olivert”(第三个字段是“1001”)。我只需要使用egrep/grep正则表达式匹配这两个数字的第四个字段值(三个冒号后面的值)。非常感谢任何答案,因为从长远来看它们将帮助我解决这个问题。

答案1

在我看来,使用这样的工具会更直接awk

  • 为您分割字段
  • 准确测试您想要的字段以获得您想要的值

例如:

awk -F: '$4 == 1001 || $4 == 1003' mypasswd

...告诉 awk:

  • 根据冒号将传入行拆分为字段,其中-F:
  • 使用“or”表达式来测试字段 4 的值为 1001 还是 1003
  • 如果上述条件为真,则打印该行(默认操作)

awk 需要一点时间来学习;要理解它的主要事情之一是它使用成对的“模式”和“动作”语句。 “模式”部分确定执行哪些“操作”语句。

您可以重写上面的 awk 以使其更加明确;通过这样做,我们可以显式打印我们想要的任何内容(例如第 5 个字段):

awk -F: '$4 == 1001 || $4 == 1003 { print $5 }'

...或者有一个空的“模式”部分——意思是,执行“动作”每一个行,然后在操作模式内测试值:

awk -F: '{ if ($4 == 1001 || $4 == 1003)  print $5 }'

要强制grep采取行动,您可以这样做:

grep -E '^([^:]*:){3}(1001|1003):' mypasswd | cut -d: -f5

告诉它从行的开头开始查找“任何不是冒号的东西,任意次数,后跟冒号”组三次,然后是 1001 或 1003,然后是冒号;打印整个匹配行,然后将其传递给cut仅打印第 5 个字段。

答案2

我可能会这样做sed

sed -n '/^.*:.*:.*:\(1001\|1003\):/p' mypasswd

抑制-n行并p在末尾打印匹配的行。

你也可以这样做grep

grep '^.*:.*:.*:1002\|1003:.*:.*:' mypasswd

答案3

正如@JeffSchaller所说,awk这是完成这项工作的工具,因为OP希望regex我们可以将两者结合起来

awk -F: '$4 ~ /^100[13]$/' mypasswd

grep这允许在该版本上进行一点高尔夫推杆

grep -E "^(.*:){3}100[13]:" mypasswd

答案4

“我只需要使用egrep/grep正则表达式匹配这两个数字的第四个字段值(三个冒号后面的值)”

如果您只需要第四个字段,请cutgrep这样使用:

$ cat mypasswd | cut -d: -f4 | grep -E '^(1001|1003)$'
1001
1003

grep模式需要锚定到行的开头和结尾,否则它可能会匹配诸如 之类的数字10010。另一种方法是grep -x -E '1001|1003'.

相关内容