我有几个这种格式的文本文件:
name: john
address: bay area
phone: 6505561234
image: /work/myimage.png
name: stark
dob: 5AD
shirt color: red
physical address: Westros
phone model: S2
email id: [email protected]
phone model: S2
name: tara
dob: 1ad
shirt color: red
physical address: Westros
email id: [email protected]
可以有多个“人员”或“联系人”。假设我想查找所有使用“S2”手机型号的人员。
我可以做一个‘grep’——它只会返回这个:
phone model: S2
phone model: S2
我可以在 grep 上使用前/后上下文 - 但这只是打印出前/后固定数量的行。如果“前一个”上下文为 3,我可能会得到如下结果:
shirt color: red
physical address: Westros
phone model: S2
---
name: tara
dob: 1ad
phone model: S2
但这不是我想要的。我希望显示整个“记录”。有没有关于如何使用标准 unix 命令执行此操作的线索?
答案1
awk 'BEGIN {RS="\n\n"} $0 ~ /PATTERN/ {print $0"\n---"}' record
只需将 PATTERN 替换为您想要的任何内容即可。
答案2
如果您将空行替换为---
,则您的文档是有效的 YAML 文件。这很好地代表了您所拥有的记录结构。
perl -p -e 's/^$/---/g' input > test.yml
然后,获取完整的记录:
ruby -e 'require "yaml";
YAML::load_documents(File.open("test.yml")) do |d|
puts d.to_yaml if d["phone model"] == "S2" rescue nil
end'
这将打印:
---
name: stark
dob: 5AD
shirt color: red
physical address: Westros
phone model: S2
email id: [email protected]
---
name: tara
dob: 1ad
phone model: S2
shirt color: red
physical address: Westros
email id: [email protected]
标记为 CW,因为您要求的是标准 Unix 工具,但ruby
显然不是。适用于 Ruby 1.8.7、1.9.3 和 2.0.0。
答案3
使用这问题我设法找到一种对块进行多行 grep 的方法:
grep -Pzo 'name:(..*\n)*phone model:.*S2.*(..*\n)*' filename \
| sed 's/^name:/---\nname:/' \
| tail -n +2
其中 (..*\n)*
是任意数量的传染性非空行。-P
启用 perl 语法,-z
允许换行搜索并-o
仅打印匹配项。Sed 用于分隔,tail 会剪切第一行。
答案4
用空行分隔的记录实际上是 fortune 文件的常见格式,并且(至少在我拥有的 fortune 版本中,Arch Linux 上的 fortune-mod)有一个-m
选项可以打印与正则表达式匹配的所有 fortune(记录)。因此,如下所示:
fortune -m "model: S2"
它将打印您的所有记录。