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)
这基本上是 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 错误,而行号大于文件中的行数将使其不打印任何内容。
这只是最低限度。要使其递归工作并处理上述行号情况,需要做一些事情。
不能只用grep. 如果ed是一个选项:
ed -s file << 'EOF'
g/match/-5p\
+5p\
+5p
EOF
Run Code Online (Sandbox Code Playgroud)
脚本基本上说:对于 /match/ 的每个匹配项,打印之前的第 5 行,然后是 5 行,然后是 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是与图案相匹配的行号match和FILENAME是当前处理的文件名路过awk。
您要使用的工具称为 sift。这基本上是一个类固醇的 grep。并行 Grep。Sift 有大量选项可以完全满足您的要求 - 特别是返回与匹配项相关的特定行,该匹配项后面可能/可能没有某些文本。
令我惊讶的是,sift 并不是主流的 gnu,因为它是用 go 语言编写的,但在 Linux 上安装得很好。IT 使用所有 cpu 并行搜索大量文本,而 grep 只需数周时间即可完成同样的工作。