显示出现次数并计算它们之间以及最后一个之后的行数

显示出现次数并计算它们之间以及最后一个之后的行数

我有这个文件:

table_01 (id, field01, field02, field03, field04)
record_01
record_02
record_03
table_02 (id, field01, field02, field03)
record_01
table_03 (id, field01, field02, field03, field04)
record_01
record_02
table_04 (id, field01, field02, field03, field04, field04)
record_01
table_05 (id, field01, field02, field03, field04)
record_01
record_02
record_03
record_04

我想要一个脚本来显示出现单词“ table”的行,并显示它们之间的行数以及最后一次出现之后的行数。

所以输出将是:

table_01 (id, field01, field02, field03, field04)
3
table_02 (id, field01, field02, field03)
1
table_03 (id, field01, field02, field03, field04)
2
table_04 (id, field01, field02, field03, field04, field04)
1
table_05 (id, field01, field02, field03, field04)
4

到目前为止我有这个脚本:

awk '$0 ~ /table/ {if (n) print NR-1-n; n=NR}' file

其输出为:

3
1
2
1

但该脚本不显示出现“ table”的行,也不显示最后一次出现之后的行。我该如何修改它以显示缺少的内容?

答案1

显然,你已经完成了 90% 的任务:

awk '/table/ {if (n) 打印 NR-1-n; n=NR;打印}
     END {if (n) 打印 NR-1-n}'             文件

你不需要$0 ~;这是暗示的。

答案2

我整理了一个 Perl 解决方案:

perl -Mfeature=say -e '
    while (<>) {
        if (/^table/) {
            $c && say $c;
            print;
            $c = 0;
            next;
        }
        $c++;
    }
    say $c;
' <input
user@server ~/[REDACTED] (git)-[REDACTED] % perl -Mfeature=say -e '
    while (<>) {
        if (/^table/) {
            $c && say $c;
            print;
            $c = 0;
            next;
        }
        $c++;
    }
    say $c;
' <input
table_01 (id, field01, field02, field03, field04)
3
table_02 (id, field01, field02, field03)
1
table_03 (id, field01, field02, field03, field04)
2
table_04 (id, field01, field02, field03, field04, field04)
1
table_05 (id, field01, field02, field03, field04)
4

答案3

我的答案假设一个场景,其中可以有空表(“空表”行/匹配行),以及一个通用场景,其中可能有额外的(非表/不匹配)行添加到输入文件中。

在这种情况下,要显示表行(匹配行)并计算其后续记录行(非匹配行)的出现次数,请使用awk,如果需要模式为^table

awk '
  /^$/ {next}
  /^table/ {
    if (precedingmatch)
      {print 0}
    else if (n)
      {print n}
    
    print; n=0; precedingmatch=1; matchesfound=1
  }
  !/^table/ {
    if (matchesfound) {n++}
    
    precedingmatch=0
  }
  END {if (matchesfound) {print n} else {print 0} }
' file.txt
  • precedingmatch0用于当后续两行是表格行时进行打印。
  • matchesfound用于忽略打印在任何第一个表行之前找到的非表行的计数。

file.txt使用一些“空表”、换行符和一些随机前置的行进行示例:

randomline_01
randomline_02
table_01 (id, field01, field02, field03, field04)
table_02 (id, field01, field02, field03)
record_01
record_02

table_03 (id, field01, field02, field03, field04)
record_01
record_02
record_03
table_04 (id, field01, field02, field03, field04, field05)
table_05 (id, field01, field02, field03, field04)

输出:

table_01 (id, field01, field02, field03, field04)
0
table_02 (id, field01, field02, field03)
2
table_03 (id, field01, field02, field03, field04)
3
table_04 (id, field01, field02, field03, field04, field05)
0
table_05 (id, field01, field02, field03, field04)
0

没有“表”行的文件、空文件或充满换行符输出的文件0

答案4

使用(以前称为 Perl_6)

~$ raku -ne 'BEGIN my $c = 0;  if /^table/ { $c && put $c; .put; $c = 0; next}; $c++;'  file

Raku 是 Perl 系列中的一种编程语言,具有对 Unicode 的高级支持。这个 Raku 解决方案遵循 @kos 和 @terdon 发布的总体大纲(Perl 语言)。

示例输入(table末尾有额外的行,尽管OP说这些不会遇到):

table_01 (id, field01, field02, field03, field04)
record_01
record_02
record_03
table_02 (id, field01, field02, field03)
record_01
table_03 (id, field01, field02, field03, field04)
record_01
record_02
table_04 (id, field01, field02, field03, field04, field04)
record_01
table_05 (id, field01, field02, field03, field04)
record_01
record_02
record_03
record_04
table_06 (id, field01, field02, field03, field04)
table_07 (id, field01, field02, field03, field04)

示例输出:

table_01 (id, field01, field02, field03, field04)
3
table_02 (id, field01, field02, field03)
1
table_03 (id, field01, field02, field03, field04)
2
table_04 (id, field01, field02, field03, field04, field04)
1
table_05 (id, field01, field02, field03, field04)
4
table_06 (id, field01, field02, field03, field04)
table_07 (id, field01, field02, field03, field04)

上面给出的答案与 @kos 和 @terdon 的 Perl 答案相同。更明确地说,块内的第一条语句可以写成$c.Bool && put $c;$c.so && put $c;,但上面的代码就足够了。


如果没有插入“非表”记录,则插入零:

0这是当record标题后面没有行时返回的代码table(类似于@Aeronautix 的答案):

~$ raku -ne 'BEGIN my $c = 0;  if /^table/ { $c && put($c-1); .put; $c = 0}; $c++; END put($c-1);'  file
table_01 (id, field01, field02, field03, field04)
3
table_02 (id, field01, field02, field03)
1
table_03 (id, field01, field02, field03, field04)
2
table_04 (id, field01, field02, field03, field04, field04)
1
table_05 (id, field01, field02, field03, field04)
4
table_06 (id, field01, field02, field03, field04)
0
table_07 (id, field01, field02, field03, field04)
0

注意:对于上面的所有答案,代码假设第一行以 开头table,并且 OP 确认在第一行之前不会出现杂散行table

但是(对于其他用户/数据源),如果record在文件顶部遇到杂散行,第一个答案将返回该杂散行之前的行数第一的表线。第二个答案将返回“一减”之前的行数第一的表线。

https://raku.org

相关内容