使用标准 unix 命令,如何抓取一堆行?

使用标准 unix 命令,如何抓取一堆行?

我有几个这种格式的文本文件:

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"

它将打印您的所有记录。

相关内容