我有一个包含大约 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
将P
打印其第一个缓冲区行,然后D
将其删除。在N
ext 周期的顶部,sed
将使用 ext 输入线补充其缓冲区N
。
如果任何点query.*\nquery
在其 10 行窗口内匹配,sed
将删除除尾随query
匹配之外的所有匹配。在下一个周期的顶部,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 -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
切掉完全适合其输入窗口的所有序列。它不会错过任何内容,并且一次不需要缓冲超过十行。如果我们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$