フラットファイルが特定の行数未満の場合は、ヘッダーとコンテンツを削除します。

フラットファイルが特定の行数未満の場合は、ヘッダーとコンテンツを削除します。

約1000万行のフラットファイルがあります。

    query
    ID1
    content1
    content2
    query
    ID2
    content3
    content4
    ...
    content21
    query
    ID3
    content22
    content23
    ...
    content81

10行未満のファイルブロックはすべて削除する必要があります。たとえば、最初のブロックには4行(content2に対するクエリ)が含まれているため、削除する必要があります。この手順は、チャンクを別のファイルに分割する前に実行する必要があります。どんな提案がありますか?

答え1

これはawkで行うことができます。

awk '
# define a long block
BEGIN{
  long = 10;
}
# output long block when new block is found
($1 == "query" && n >= long){
  print s;
}
# new block
($1 == "query"){
  s = "";
  n = 0;
}
# all lines
{
  s = (s != "") ? s "\n" $0 : $0;
  n++;
}
# output the long block if it is the last one in the file
END{
  if (n >= long){
    print s;
  }
}
' input.file > output.file

答え2

sed -e:q -e'$!N;s/\n/&/9;tS' -e'$!bq'     -e:S    \
         -e's|^query.*\n\(query\)|\1|;tq' -e'/\n/{P;D;}'

sedこれにより、入力ファイルの現在の10行が常にバッファに保持されます。各汎用入力ラインについて、最初のバッファラインが印刷された後に削除されsedます。拡張サイクルの上部では、対応するバッファは拡張入力ラインで満たされます。PDNsedN

query.*\nquery10行ウィンドウ内に一致する点がある場合は、末尾の一致を除くすべての項目がsed削除されます。query次のサイクルの先頭でsed入力を再テストする前に、スライドウィンドウバッファの10行すべてを補充するまで入力が収集されます。

以下は簡単なデモです:

for i in      3 6 9 12 15 18                                      
do         
      printf "%s %s %s %s%0${i}s" query ID1 content1 content2
done| tr \  \\n| nl -ba -w1 |
sed -e:q -e'$!N;s/\n/&/9;tS' -e'$!bq'   -e:S    \
         -e's|^[0-9]*.query.*\n\([0-9]*.query\)|\1|;tq' \
         -e'/\n/{P;D;}'

nl出力に合わせて正規表現を少し修正しました。

16  query
17  ID1
18  content1
19  content2
20  
21  
22  
23  
24  
25  
26  
27  
28  query
29  ID1
30  content1
31  content2
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  query
44  ID1
45  content1
46  content2
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  query
62  ID1
63  content1
64  content2
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  

sed入力ウィンドウに正確に収まるすべてのシーケンスを切り取ります。何も見逃せず、一度に10行以上をバッファリングする必要もありません。lスクリプトに ook を追加すると、sedバッファがどのように見えるかを確認できます。

for i in      3 6 9 12 15 18                                      
do         
      printf "%s %s %s %s%0${i}s" query ID1 content1 content2
done| tr \  \\n| nl -ba -w1 |
sed -ne:q -e'$!N;l;s/\n/&/9;tS' -e'$!bq'   -e:S    \
          -e's|^[0-9]*.query.*\n\([0-9]*.query\)|\1|;tq' \
          -e'/\n/{P;D;}'

1\tquery\n2\tID1$
1\tquery\n2\tID1\n3\tcontent1$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t\n6\t$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t\n6\t\n7\tquery$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t\n6\t\n7\tquery\n8\tID\
1$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t\n6\t\n7\tquery\n8\tID\
1\n9\tcontent1$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t\n6\t\n7\tquery\n8\tID\
1\n9\tcontent1\n10\tcontent2$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t\n12\t$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t\n12\t\n13\t$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t\n12\t\n13\t\n14\t$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t\n12\t\n13\t\n14\t\n\
15\t$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t\n12\t\n13\t\n14\t\n\
15\t\n16\tquery$
16\tquery\n17\tID1$
16\tquery\n17\tID1\n18\tcontent1$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2\n20\t$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2\n20\t\n21\t$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2\n20\t\n21\t\n22\t$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2\n20\t\n21\t\n22\t\n23\
\t$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2\n20\t\n21\t\n22\t\n23\
\t\n24\t$

関連情報