発生回数を表示し、その間と最後の行以降の行数を計算します。

発生回数を表示し、その間と最後の行以降の行数を計算します。

私はこのファイルを持っています:

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;印刷}
     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次の2行がテーブル行の場合は、印刷に使用されます。
  • 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は、Unicodeを高度にサポートするPerlファミリのプログラミング言語です。このRakuソリューションは、@kosと@terdonによって公開された一般的な概要(Perl)に従います。

入力例(tableOPでこれらの内容が発生しないと述べたにもかかわらず、最後に追加の行があります):

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;orで書くことができますが、$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

注:上記のすべての答えに対して、コードは最初の行がで始まると仮定し、tableOPは最初の行の前に誤った行がないことを確認しますtable

ただし、(他のユーザー/データソースの場合)recordファイルの上部に誤った行がある場合、最初の答えはその間違った行の前の行数を返します。最初テーブルライン。 2番目の答えは、「1減算」より前の行数を返します。最初テーブルライン。

https://raku.org

関連情報