grep在比赛之前和之后返回第N和Mth行


12

我知道使用grep可以使用字段-A-B从匹配项中提取上一行和下一行。

但是,根据指定的行数,它们会拉入比赛之间的所有行。

grep -r -i -B 5 -A 5 "match" 

我想只收到5 在比赛之前线和5 线的比赛,除了匹配的行之后,并没有得到之间的界线。

有办法做到这一点grep吗?


1
您可以通过将其输送到sed中来实现。我刚刚对此进行了测试,但它确实有效,但是只有在文件中有1个完全匹配的情况下,它才有效: grep -r -i -B 5 -A 5 "match" | sed -e 1b -e '$!d'
Terrance

正如您所提到的,@ Terrance感谢您的建议,因为我正在收集1000条线,所以这行不通。
chollida

我不认为grep会自己工作...我正在为您制作bash脚本
Joshua Besneatte

没问题!有兴趣查看您得到什么答案。=)
Terrance

是一个文件还是多个文件?
约书亚·贝斯内特

Answers:


1

您要使用的工具称为sift。这基本上是类固醇的一种grep。Grep并行。Sift有很多选项可以精确地执行您想要的操作-特别是要返回相对于匹配项的特定行,该匹配项可能/可能不会/在某些文本之后。

令人惊讶的是,sift不是主流的gnu,因为它是用go语言编写的,但可以很好地安装在Linux上。IT使用所有cpus大量文本进行并行搜索,而grep只需花费数周的时间即可完成相同的操作。

筛查网站-查看示例


欢迎来到AskUbuntu,谢谢您的回答。您需要提供一个可以解决此特定问题的CLI示例,而不是提供一个到sift网站的链接。毕竟,这是一个问答环节,谢谢。
伯纳德·魏

12

如果:

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

+1,但您能否解释一下的语义/match/ {matched[NR]}?我从未见过将数组或变量作为整个命令。是否将每个匹配行的当前记录号放入数组中。

这真是一个奇怪的现象:如果您引用未分配的数组元素,则该键会添加到数组中(没有值)。然后该键显示在表达式中key in array。我正在做的是记住模式出现的行号
glenn jackman

6

这基本上是Glenn的解决方案,但是使用Bash,Grep和sed实现。

grep -n match file |
    while IFS=: read nr _; do
        sed -ns "$((nr-5))p; $((nr))p; $((nr+5))p" file
    done

请注意,行号小于1将导致sed错误,而行号大于文件中的行数将使其不打印任何内容。

这仅仅是最低要求。为了使其能够递归工作并处理上述行号,需要做一些事情。


6

不能仅用grep。如果ed选择:

ed -s file << 'EOF' 
g/match/-5p\
+5p\
+5p
EOF  

该脚本基本上说:对于/ match /的每个匹配项,在此之前打印5行,然后在其后打印5行,然后在其后打印5行。


5
@ubashu您认为对OP提供简单的单位“ grep无法完成”会更有用吗?我提供了我认为是解决OP问题的好选择。在帮助中心中:“具体的问题是什么?请确保您的答案提供了这一点-或可行的替代方案。答案可以是'不要这样做',但还应包括'试试看'。 。”
JoL

ed永远的答案,因为ed是标准的文本编辑器。
甜点

5
@ubashu虽然不是grep答案,但是“您不能用X来解决,但可以用Y来解决,这就是方法”的答案仍然是有效的答案,因为您不仅要回答OP的问题,而且还提供了另一种选择那会起作用。这是一种有效的答案。
托马斯·沃德

5
awk '/match/{system("sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME)}' infile

在这里,我们使用awk的函数来调用外部命令,以打印awk与pattern匹配的行,在匹配之前和之后有 5 行。system(command)sedmatch

语法很简单,您只需要将外部命令本身放在双引号及其开关内,然后转义要传递给命令的内容即可,与awk自身选项相关的其他所有内容都应在引号之外。所以下面的sed

"sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME

翻译成:

sed -n "NR-5p; NRp; NR+5p" FILENAME

NR是与图案相匹配的行号matchFILENAME是当前处理的文件名路过awk


2

使用@glenn的示例文本文件并使用perl而不是awk:

$ perl -n0E 'say /(.*\n)(?=(?:.*\n){4}(.*match.*\n)(?:.*\n){4}(.*\n))/g' ex

将给出相同的结果,但运行速度更快:

a
f match
k
d
i match
n

若昂,你展示在LQ审查队列和@waltinator了投票删除,这样下一次是点点更详细的... ;-) 此外+1你出来的LQ队列... :P
Fabby

1
@JJoao低质量审核队列。您的答案可能在那里被接受,因为它是90%的代码。
wjandrea

1
@JJoao 90%的数字只是我的解释方式。我不知道实际使用什么启发式方法。
wjandrea

1
梅诺斯岛咖啡馆,埃斯克里塔!@JJoao :D ;-):D
Fabby

1
@Fabby:Semcafénada funciona:D-可能会出现在LCQ中(=低咖啡排队)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.