所以,我试图在/ etc / passwd的第5个字段中查找某些单词。 例如:
jonesc:x:1053:1001:Cathy Jones:/export/home/jonesc:/bin/ksh
smiths:x:1049:1000:Sue Williams:/export/home/smiths:/bin/csh
smitha:x:1050:1001:Amy Smith:/export/home/smitha:/bin/bash
让我们说我正在寻找'史密斯'这个词?我如何才能在包含名称的第5个字段中查找它,而不是查看整行?
我可以使用awk轻松完成此操作,但我要求用sed执行此操作。
我要求做的是将第5个字段中包含Smith或Jones的/ etc / passwd中的匹配输出到名为smith_jones.txt的文件中。
我用sed将输出写入文件没有问题,我只是坚持我应该只在第5场中查找。 Awk将使用5美元,但我找不到与sed类似的东西。
没有找到完整的答案交给我,而是朝着正确的方向努力。
答案 0 :(得分:5)
Awk将是这项工作的正确工具:
awk '$5 ~ /smith|jones/{print}' /etc/passwd > output.txt
但是既然你要求sed解决方案,那么你可以使用这样的东西:
sed -n '/[^:]*:[^:]*:[^:]*:[^:]*:\(smith\|jones\)/p' /etc/passwd
每个[^:]*
除了:
以外的所有内容都会匹配零次或多次。
您还可以使用范围元序列重复以前的模式:\{x,y\}
:
sed -n '/\([^:]*:\)\{4\}\(smith\|jones\)/p' /etc/passwd
正如您所看到的,这将有助于您进一步简化正则表达式。
-n
默认情况下不打印,/pattern/p
会打印与pattern
匹配的所有内容
如果您想匹配用户名的中间位置,可能需要在[^:]*
之前添加另一个\(smith\|jones\)
,例如:
sed -n '/\([^:]*:\)\{4\}[^:]*\(th\|es\)/p' /etc/passwd
将匹配Smith
和Jones
。
正如评论中所指出的,您还可以使用扩展正则表达式来避免所有这些反斜杠:
sed -E -n '/([^:]*:){4}(smith|jones)/p' /etc/passwd
传统上GNU sed使用-r
启用ERE,BSD sed使用-E
。但GNU sed支持-E
标志,即使它没有文档。
答案 1 :(得分:0)
这应该有效:
sed -n '/^\([^:]*:\)\{4\}[^:]*\(Jones\|Smith\)/p' /etc/passwd
^\([^:]*:\)\{4\}
匹配以:
分隔的前四个字段,因此第五个字段与名称(琼斯和史密斯)匹配。
答案 2 :(得分:0)
尝试一下:
sed -n ":1
/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*Smith[^:]*:.*$/ {p
n
b1}
/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*Jones[^:]*:.*$/{p}"
-n
指示sed
不打印任何内容
:1
定义标签
/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*Smith[^:]*:.*$/
正则表达式匹配第5个字段中包含Smith
的任何字符串,其中字段以:
分隔。
p
是打印当前行的命令。
n
是一个将下一行加载到缓冲区的命令。
b1
转到标签1
sed
一次读取一行文件。当前行存储在缓冲区中。如果在第5个字段中找到Smith
,则打印该行,并将下一行存储到缓冲区中,然后转到标签1.否则,如果在第5个字段中找到Jones
,则在打印缓冲区。
测试:
$ sed -n ":1
/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*Smith[^:]*:.*$/ {p
n
b1}
/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*Jones[^:]*:.*$/{p}" /etc/passwd >> smith_jones.txt
$ cat smith_jones.txt
jonesc:x:1053:1001:Cathy Jones:/export/home/jonesc:/bin/ksh
smitha:x:1050:1001:Amy Smith:/export/home/smitha:/bin/bash