如何使用awk打印下一行或上一行?

时间:2019-02-07 18:05:31

标签: awk

我有一个8列的文件

1743 abc 04 10 29 31 34 35
1742 def 11 19 21 23 27 52
1741 ghi 15 18 20 32 48 49

,我还有awk行,可打印出包含某些特定数字的完整行。代码是

awk -v col=1 '{ delete c; for (i=col; i<=NF; ++i) ++c[$i];
if (c['"$1"']>0 && c['"$2"']>0 && c['"$3"']>0 && c['"$4"']>0) print }' 
< input_file

(变量$ 1,$ 2,$ 3和$ 4是因为我在bash上使用它)。

在前面的示例中,当我输入数字11 21 27和52时,将获得1742行。

如何打印下一行或上一行?像上一个示例一样,如果我使用数字11 21 27和52,我将如何选择1743行或1741行?

2 个答案:

答案 0 :(得分:0)

$ cat a.sh
echo "BEFORE"

awk -v p1="$1" -v p2="$2" -v p3="$3" -v p4="$4" -v col=1 -f before.awk file

echo "AFTER"

awk -v p1="$1" -v p2="$2" -v p3="$3" -v p4="$4" -v col=1 -f after.awk file

引用@triplee:“要打印上一行,请记住变量中的上一行。”

$ cat before.awk
prev { delete c;
  for (i=col; i<=NF; ++i) ++c[$i]
  if (c[p1]>0 && c[p2]>0 && c[p3]>0 && c[p4]>0) print prev
}
{ prev = $0 }

再次,@ triplee:“要打印下一行,请记住您要的,并在下一次迭代时打印并重置此变量。”

$ cat after.awk
f { print; f = 0 }
{
  delete c;
  for (i=col; i<=NF; ++i) ++c[$i]
  if (c[p1]>0 && c[p2]>0 && c[p3]>0 && c[p4]>0) f = 1
}

$ ./a.sh 11 21 27 52
BEFORE
1743 abc 04 10 29 31 34 35
AFTER
1741 ghi 15 18 20 32 48 49

答案 1 :(得分:0)

采用双重扫描的另一种方法

$ awk -v search="11 21 27 52" -v offset=-1 '
           NR==FNR {n=split(search,s); 
                    for(i=1;i<=n;i++) if(FS $0 FS !~ FS s[i] FS) next; 
                    line=NR; next} 
           FNR==line+offset' file{,}

1743 abc 04 10 29 31 34 35

您可以将offset设置为任何值(不仅仅是-1,0,1)。

N.B。虽然它只能找到一个匹配项,但是如果有多个匹配项,则只会报告最后一个匹配项。这可以通过将匹配的行号而不是标量值(此处为line变量)保留在数组中来解决。