如何在awk中打​​印记录的行号?

时间:2019-01-23 23:41:53

标签: awk

我正在使用awk处理多行记录,其中每条记录的字段数未知。这有助于过滤非常大的文件中的记录,因此了解返回记录的行号将很有帮助。我尝试为每个记录赋予一个变量,但这似乎很麻烦,有没有更好的方法呢?

数据示例(包括行号):

{
  user: {
    street: '111 Cool Street'
  }
}

代码示例:

1 | data1 - good
2 |    foo bar
3 |
4 | data2 - bad
5 |    foo bar
6 |    pet cat
7 |    name snuggles
8 |
9 | data3 - good
10|    foo bar
11|    color blue

我正在寻找的输出将是这样的:

BEGIN {RS =""; FS="\n"; ORS="\n\n"; OFS=""; x=0}
{
  { x += NF + 1; }
  { if ($1 ~ /bad/) { next; } }
  { print "[", x - NF, "]\n", $0; }
}

有没有更好的方法可以做到这一点?

4 个答案:

答案 0 :(得分:2)

总的来说,我认为您的方法很好,不会认为它是hackey。

您可能会考虑进行一些小的调整,以使其变得更简单:

BEGIN {RS =""; FS="\n"; ORS="\n\n"; OFS=""; x=1}
!($1 ~ /bad/) { print "[", x, "]\n", $0; }
{ x += NF + 1; }

答案 1 :(得分:1)

请您尝试一次,仅对样品进行测试。

awk '
/data[0-9]+/{
  flag=$NF=="bad"?"":1
  count=""
}
flag && NF>2{
  if(++count==1){
    print "["$1"]"
    sub(/.*\| /,"")
  }
  sub(/.*\|/,"")
  print
}'   Input_file

答案 2 :(得分:1)

您的方法似乎并不坏,尽管我可以将其调整为:

$ cat tst.awk
BEGIN { RS=""; ORS="\n\n"; FS="\n" }
{
    nr += prevNf + 1
    if ($1 ~ /good/) {
        print "[" nr "]\n" $0
    }
    prevNf = NF
}

$ awk -f tst.awk file
[1]
data1 - good
   foo bar

[9]
data3 - good
   foo bar
   color blue

但这是一个替代方案:

$ cat tst.awk
!NF { prt(); next }
{
    nrs[++numLines] = NR
    rec[numLines]   = $0
}
END { prt() }

function prt(   lineNr) {
    if (rec[1] ~ /good/) {
        printf "[%d]\n", nrs[1]
        for (lineNr=1; lineNr<=numLines; lineNr++) {
            print rec[lineNr]
        }
        print ""
    }
    delete rec
    numLines = 0
}

$ awk -f tst.awk file
[1]
data1 - good
   foo bar

[9]
data3 - good
   foo bar
   color blue

使用上述方法,您不仅可以在一行上测试好坏,还可以做更多的事情,并且可以根据需要打印每条记录的所有行或任何行的输入行号。

答案 3 :(得分:0)

如果可以选择Perl,则可以在下面尝试

$ cat caffein.txt
data1 - good
   foo bar

data2 - bad
   foo bar
   pet cat
   name snuggles

data3 - good
   foo bar
   color blue

$ perl -0777 -ne ' s/^/++$x." "/mge; while(/(^\d+)(\s*data.+?good.+?)(\n\d+\s+\n\d+\s+|\Z)/gms) { $x="[$1] $2\n\n";$x=~s/^\d+/ /mg; print $x } ' caffein.txt
[1]  data1 - good
     foo bar

[9]  data3 - good
     foo bar
     color blue


$

或对于不匹配的“不良”具有否定的前瞻性

$ perl -0777 -ne ' s/^/++$x." "/mge; while(/(^\d+)(\s*data.+?(?!bad).+?)(\n\d+\s+\n\d+\s+|\Z)/gms) { $x="[$1] $2\n\n";$x=~s/^\d+/ /mg; print $x } ' caffein.txt