获取数据背后的序号

获取数据背后的序号

我的输入文件:

{empty line}
Test #1
data
{empty line}
Test #2
data
{empty line}
Test #3
{empty line}
Test #4
data
{empty line}
Test #5

预期输出:

1
2
4

如果使用简单的 bash 脚本在每个测试下都有可用数据,如何获取序列号(在主题标签之后)?

编辑:每个测试下的数据包含很少的值,例如日期、时间、差异等。两个测试之间有多于一根数据线。每个测试之间有一个空行。 “测试”数字始终是从 1 开始的严格递增的正整数序列。

答案1

这将做到这一点:

awk -F ' #' '
  function maybePrint() {
    if (NR > 1 && NR > lastLine + 1) {print lastSeq}
  }
  $1 == "Test" {
    maybePrint()
    lastSeq = $2
    lastLine = NR
  }
  END {
    maybePrint()
  }
' file

更改要求并不好,但因为我喜欢拼图:如果文件有空行:

sed -n '
    /^Test #/ {
      s///
      =
      p
    }
    $=
  ' file \
| paste - - \
| awk -F '\t' '
    NR > 1 && $1 - prevLine > ($2 ? 2 : 0) {print prev} 
    {prevLine = $1; prev = $2}
  '

答案2

如果数据中没有主题标签:

sed -n 'N;/#.*#/D;s/.*#//;P' file

更清晰的选项:

sed -nE 'N;/(.*#)[0-9]+\n\1/D;s/.*#//;P' file

模式(.*#)[0-9]+\n\1使用主题标签跟踪重复的行。

答案3

使用 时sed,您通常会在N;P;D模式和使用保留空间之间进行选择:

N;P;D方法

您可以使用该方法在缓冲区中始终保留两行连续的行,方法是N在开头附加一行,P仅打印第一行并通过D删除第一行开始新的循环:

sed '$!N;/\ndata/!D;s/.*#//;P;D'
  • $!N如果这还不是最后一行,则追加下一行
  • /\ndata/匹配第二行为 的双行data!反转匹配并D开始下一个循环,缓冲区中仅包含第二行。因此,如果第二行不以 开头data,则继续下一对
  • 如果我们到达这里,我们知道第二行以 开头data,因此s/.*#//将删除直到 的所有内容#P将打印第一行(现在只是数字),并D删除下一个循环的第一行(注意两个data在这种情况下你不知道该怎么做。

等待空间进近

将要打印信息的行保留在h旧空间中,但仅在触发行上打印:

sed '/data/!{h;d;};x;s/.*#//'
  • /data/!寻址所有不包含data.将这些行放在h旧空间中并d删除以重新开始而不输出
  • 如果我们在这里,data确实匹配,那么更改缓冲区以将保存的行获取到模式空间,删除直到with 的x内容 并通过默认输出打印结果#s/.*#//

答案4

awk '{a[++i]=$0}/data/{for(x=NR-1;x<=NR;x++)print a[x]}' file| awk -F "#" '/Test/{print $2}'

输出

1
2
4

相关内容