如何匹配行开头的文本并打印前 X 行以及匹配的行?

如何匹配行开头的文本并打印前 X 行以及匹配的行?

我发现了一个类似的问题这里,但这并不完全是我想要的。

假设我有一个像这样的文本文件:

[...]

age: 10
country: United States
city: New York
name: John

age: 27
country: Canada
city: Toronto
name: Robert

age: 32
country: Mexico
city: Guadalajara
name: Pedro

[...]

我想匹配以“name: Robert”开头的行,并打印前 3 行以及匹配的结果,只得到这些行:

age: 27
country: Canada
city: Toronto
name: Robert

我如何在终端中执行此操作?

答案1

使用grep

$ grep -B3 '^name: Robert$' input_file
age: 27
country: Canada
city: Toronto
name: Robert

答案2

您已经有了最好的方法,只需使用grep -B,但您也可以在“段落模式”下使用 perl 。此模式由开关启用-00,意味着“行”现在由两个连续的换行符定义,基本上是一个段落。这可以让您执行以下操作:

$ perl -00 -ne 'print if /name: Robert\b/' file
age: 27
country: Canada
city: Toronto
name: Robert

$

awk您还可以通过将记录分隔符 ( RS) 设置为空 ( )来执行相同的操作''

$ awk -v RS='' '/name: Robert$/' file
age: 27
country: Canada
city: Toronto
name: Robert
$

awk 的另一个优点是不会像 perl 那样打印额外的换行符。

答案3

数据的格式与 GNU recutils 使用的“recfile 格式”相同。这意味着我们可以像这样查询您的文件:

$ recsel -e 'name = "Pedro"' file
age: 32
country: Mexico
city: Guadalajara
name: Pedro

要获取 20 岁或以上每个人的姓名:

$ recsel -e 'age >= 20' -P name file
Robert

Pedro

ETC。

请参阅info recutilsGNU reutils 网站了解更多信息。

答案4

使用行编辑器,ed我们首先选择目标行(g//),然后在其周围创建一个范围(-3,.),并在该范围上运行命令(p)

ed -s inp <<\eof
g/^name: Robert$/-3,.p
eof

## Gnu sed in extended regex mode
## collect 4 lines in pattern space then print the whole pattern space on match else clip first line and append the next

sed -E ':1;$!{N;/(.*\n){3}/!b1;/\nname: Robert$/b};D' file

# using the -p option to autoprint current record 

perl -00 -pe '($_)=/((?:.*\n){3}name: Robert\n)/' file

输出:

age: 27
country: Canada
city: Toronto
name: Robert

相关内容