grep 返回匹配前后的第 N 行和第 M 行

cho*_*ida 12 command-line grep awk

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

但是,他们根据指定的行数在匹配之间拉入所有行。

grep -r -i -B 5 -A 5 "match" 
Run Code Online (Sandbox Code Playgroud)

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

有没有办法做到这一点grep

gle*_*man 12

如果:

cat file
Run Code Online (Sandbox Code Playgroud)
a
b
c
d
e
f match
g
h
i match
j
k
l
m
n
o
Run Code Online (Sandbox Code Playgroud)

然后:

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
Run Code Online (Sandbox Code Playgroud)
a
f match
k
d
i match
n
Run Code Online (Sandbox Code Playgroud)


wja*_*rea 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
Run Code Online (Sandbox Code Playgroud)

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

这只是最低限度。要使其递归工作并处理上述行号情况,需要做一些事情。


JoL*_*JoL 6

不能只用grep. 如果ed是一个选项:

ed -s file << 'EOF' 
g/match/-5p\
+5p\
+5p
EOF  
Run Code Online (Sandbox Code Playgroud)

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

  • @ubashu你认为这对OP给出一个简单的平面“它不能用grep完成”会更有帮助吗?我正在提供我认为是解决 OP 问题的好方法。来自帮助中心:“这个问题具体要问什么?确保你的答案提供了这一点——或者一个可行的替代方案。答案可以是‘不要那样做’,但它也应该包括‘试试这个’ .” (5认同)
  • @ubashu 虽然这不是一个 `grep` 答案,“你不能用 X 来做,但你可以用 Y 来做,这就是方法”的答案仍然是一个有效的答案,因为你不仅回答了 OP 的问题,而且你也提供一个可行的替代方案。这是这里的有效答案类型。 (5认同)

αғs*_*нιη 5

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

这里我们使用awk的函数调用外部命令来打印awk与模式匹配前后5行的行。system(command)sedmatch

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

"sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME
Run Code Online (Sandbox Code Playgroud)

翻译成:

sed -n "NR-5p; NRp; NR+5p" FILENAME
Run Code Online (Sandbox Code Playgroud)

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


Bra*_*eld 1

您要使用的工具称为 sift。这基本上是一个类固醇的 grep。并行 Grep。Sift 有大量选项可以完全满足您的要求 - 特别是返回与匹配项相关的特定行,该匹配项后面可能/可能没有某些文本。

令我惊讶的是,sift 并不是主流的 gnu,因为它是用 go 语言编写的,但在 Linux 上安装得很好。IT 使用所有 cpu 并行搜索大量文本,而 grep 只需数周时间即可完成同样的工作。

Sift 网站 - 查看示例