我知道使用grep可以使用字段-A
并-B
从匹配项中提取上一行和下一行。
但是,根据指定的行数,它们会拉入比赛之间的所有行。
grep -r -i -B 5 -A 5 "match"
我想只收到5 次在比赛之前线和5 日线的比赛,除了匹配的行之后,并没有得到之间的界线。
有办法做到这一点grep
吗?
我知道使用grep可以使用字段-A
并-B
从匹配项中提取上一行和下一行。
但是,根据指定的行数,它们会拉入比赛之间的所有行。
grep -r -i -B 5 -A 5 "match"
我想只收到5 次在比赛之前线和5 日线的比赛,除了匹配的行之后,并没有得到之间的界线。
有办法做到这一点grep
吗?
Answers:
您要使用的工具称为sift。这基本上是类固醇的一种grep。Grep并行。Sift有很多选项可以精确地执行您想要的操作-特别是要返回相对于匹配项的特定行,该匹配项可能/可能不会/在某些文本之后。
令人惊讶的是,sift不是主流的gnu,因为它是用go语言编写的,但可以很好地安装在Linux上。IT使用所有cpus大量文本进行并行搜索,而grep只需花费数周的时间即可完成相同的操作。
如果:
cat file
a
b
c
d
e
f match
g
h
i match
j
k
l
m
n
o
然后:
awk '
{line[NR] = $0}
/match/ {matched[NR]}
END {
for (nr in matched)
for (n=nr-5; n<=nr+5; n+=5)
print line[n]
}
' file
a
f match
k
d
i match
n
/match/ {matched[NR]}
?我从未见过将数组或变量作为整个命令。是否将每个匹配行的当前记录号放入数组中。
key in array
。我正在做的是记住模式出现的行号
不能仅用grep
。如果ed
选择:
ed -s file << 'EOF'
g/match/-5p\
+5p\
+5p
EOF
该脚本基本上说:对于/ match /的每个匹配项,在此之前打印5行,然后在其后打印5行,然后在其后打印5行。
ed
是永远的答案,因为ed
是标准的文本编辑器。
grep
答案,但是“您不能用X来解决,但可以用Y来解决,这就是方法”的答案仍然是有效的答案,因为您不仅要回答OP的问题,而且还提供了另一种选择那会起作用。这是一种有效的答案。
awk '/match/{system("sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME)}' infile
在这里,我们使用awk的函数来调用外部命令,以打印awk与pattern匹配的行,在匹配之前和之后有第 5 行。system(command)
sed
match
语法很简单,您只需要将外部命令本身放在双引号及其开关内,然后转义要传递给命令的内容即可,与awk
自身选项相关的其他所有内容都应在引号之外。所以下面的sed:
"sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME
翻译成:
sed -n "NR-5p; NRp; NR+5p" FILENAME
使用@glenn的示例文本文件并使用perl而不是awk:
$ perl -n0E 'say /(.*\n)(?=(?:.*\n){4}(.*match.*\n)(?:.*\n){4}(.*\n))/g' ex
将给出相同的结果,但运行速度更快:
a
f match
k
d
i match
n
grep -r -i -B 5 -A 5 "match" | sed -e 1b -e '$!d'