我知道-A
-B
-C
可以用来显示 grep 关键字的上下文。
我的问题是,如何在不同的关键字上显示不同的上下文?
例如,我如何-A 5
为猫、-B 4
狗和-C 1
猴子显示:
egrep -A3 "cat|dog|monkey" <file>
// this just show 3 after lines for each keyword.
我认为没有任何方法可以通过单个 grep 调用来做到这一点,但是您可以通过 grep 对每个变量运行一次并连接输出:
var=$(grep -n -A 5 cat file)$'\n'$(grep -n -B 4 dog file)$'\n'$(grep -n -C 1 monkey file)
var=$(sort -un <(echo "$var"))
nowecho "$var"
将产生与您从单个命令中获得的相同的输出,加上行号和上下文指示符(:
前缀表示与模式完全匹配的行,-
前缀表示由于-A
-B
and/or-C
选项而包含的行) .
到目前为止,我包含行号的原因是为了保留如果您设法在一个语句中做到这一点,您会看到的结果的顺序。如果您喜欢它们,很好,但如果不喜欢,您可以使用以下行将它们删掉:
var=$(cut -d: -f2- <(echo "$var") | cut -d- -f2-)
这将通过一次以剪切精确匹配行的前缀,然后再次剪切上下文匹配的前缀。
漂亮的?不。但它有效。
恐怕grep
不会那样做。您将不得不使用不同的工具。也许编写自己的程序。
这样的事情会做到这一点:
awk '
BEGIN{ ARGV[ARGC++] = ARGV[1] }
function prtB(nr) { for (i=FNR-nr; i<FNR; i++) print a[i] }
function prtA(nr) { for (i=FNR+1; i<=FNR+nr; i++) print a[i] }
NR==FNR{ a[NR]; next }
/cat/ { print; prtA(5) }
/dog/ { prtB(4); print }
/monkey/ { prtB(1); print; prtA(1) }
' file
检查函数中循环的数学。例如,您没有说要如何处理包含猴子和狗的行。
编辑:这是一个未经测试的解决方案,它可以在任何匹配项周围打印最大上下文,并让您在命令行上指定上下文,并且不会像上述廉价而愉快的解决方案那样使用尽可能多的内存:
awk -v cxts="cat:0:5\ndog:4:0\nmonkey:1:1" '
BEGIN{
ARGV[ARGC++] = ARGV[1]
numCxts = split(cxts,cxtsA,RS)
for (i=1;i<=numCxts;i++) {
regex = cxtsA[i]
n = split(regex,rangeA,/:/)
sub(/:[^:]+:[^:]+$/,"",regex)
endA[regex] = rangeA[n]
startA[regex] = rangeA[n-1]
regexA[regex]
}
}
NR==FNR{
for (regex in regexA) {
if ($0 ~ regex) {
start = NR - startA[regex]
end = NR + endA[regex]
for (i=start; i<=end; i++) {
prt[i]
}
}
}
next
}
FNR in prt
' file
将 cxts 变量中搜索到的模式与您的 RS 值分开,默认为换行符。