查找与块格式不匹配的行块
Posted
技术标签:
【中文标题】查找与块格式不匹配的行块【英文标题】:Find block of lines that does not match block format 【发布时间】:2021-02-07 09:50:18 【问题描述】:我有一个格式如下的大文件
0 0 0 0
5522 -365290 -441287 -78074
-39490 -30774 7921 82126
1391898 1139913 792801 2672554
0 0 0 0
4906 -366163 -441744 -77614
-39125 -31009 7332 81061
1412373 1142806 793817 2837307
0 0 0 0
我需要找到那些与此格式不匹配的行块。 例如以零为界的四行数字块 行:
0 0 0 0
15965 -463075 -549574 -89243
-64152 -45009 17963 103367
-189486 -165820 -128253 -236536
1243199 1029337 734157 2290154
0 0 0 0
与格式不匹配。 我只需要找到这样的块。 我会根据上下文手动修复它们。
同时我在 vim 中有以下查询:
/\s0 0\n.*\n.*\n.*\n/^\(\(\s0\)\@!.\)*$
这实际上不起作用。 我很确定这部分:
\s0 0\n.*\n.*\n.*\n
没问题。但后来我被困住了。
可能最好使用sed
或awk
来解决它。
请指教。
谢谢!
【问题讨论】:
能否请您在您的问题中发布预期输出的示例,并让我们知道以更清楚,谢谢。 @RavinderSingh13 vim 搜索的标准输出。它只是将您带到您正在寻找的下一个事件。 【参考方案1】:所以下面的 vim 搜索查询完成了我想要实现的目标
/\(\s\+0\)\4\n.*\n.*\n.*\n^\(\(\s+0\)\4\)\@!
它找到包含在两行之间的所有行块,每行四个0
,并且还有其他行数,然后是 3。
\(\s\+0\)\4
查找一行 4 个零,这样每个 0 前面至少有一个空格
\n.*\n.*\n.*
后跟 3 行任何内容
\n^\(\(\s+0\)\4\)\@!
后面没有 4 个零的行
所以它会找到这样的块
0 0 0 0
15965 -463075 -549574 -89243
-64152 -45009 17963 103367
-189486 -165820 -128253 -236536
1243199 1029337 734157 2290154
0 0 0 0
然后像这样阻止
0 0 0 0
15965 -463075 -549574 -89243
-64152 -45009 17963 103367
0 0 0 0
谢谢
【讨论】:
【参考方案2】:我假设您的输入文件如下所示。
$ cat block_zeros.txt
0 0 0 0
5522 -365290 -441287 -78074
-39490 -30774 7921 82126
1391898 1139913 792801 2672554
0 0 0 0
4906 -366163 -441744 -77614
-39125 -31009 7332 81061
1412373 1142806 793817 2837307
0 0 0 0
15965 -463075 -549574 -89243
-64152 -45009 17963 103367
-189486 -165820 -128253 -236536
1243199 1029337 734157 2290154
0 0 0 0
5000 -300000 -400000 -70000
-30000 -30000 7000 80000
0 0 0 0
$
而且你需要删除模式
0 0 0 0
15965 -463075 -549574 -89243
-64152 -45009 17963 103367
-189486 -165820 -128253 -236536
1243199 1029337 734157 2290154
0 0 0 0
预期的输出如下所示。
0 0 0 0
5522 -365290 -441287 -78074
-39490 -30774 7921 82126
1391898 1139913 792801 2672554
0 0 0 0
4906 -366163 -441744 -77614
-39125 -31009 7332 81061
1412373 1142806 793817 2837307
0 0 0 0
5000 -300000 -400000 -70000
-30000 -30000 7000 80000
0 0 0 0
如果以上是您所期望的,那么您可以通过以下步骤完成。
-
以 0 0 0 0 作为记录的开头,在看到另一个 0 0 0 0 模式之前加入后续行。
这可以使用
来完成$ perl -ne ' if( /(?=^\s*0\s+0\s+0\s+0\s+?)(^.+?)\n/smgo ) print "\n$1" else chomp($_); print "$_" ' block_zeros.txt
0 0 0 0 5522 -365290 -441287 -78074 -39490 -30774 7921 82126 1391898 1139913 792801 2672554
0 0 0 0 4906 -366163 -441744 -77614 -39125 -31009 7332 81061 1412373 1142806 793817 2837307
0 0 0 0 15965 -463075 -549574 -89243 -64152 -45009 17963 103367 -189486 -165820 -128253 -236536 1243199 1029337 734157 2290154
0 0 0 0 5000 -300000 -400000 -70000 -30000 -30000 7000 80000
0 0 0 0
$
现在删除不需要的模式。将上述输出通过管道传递到另一个 perl 命令,如下所示
$ perl -ne ' if( /(?=^\s0\s+0\s+0\s+0\s+?)(^.+?)\n/smgo ) 打印"\n$1" else chomp($);打印 "$" ' block_zeros.txt | perl -ne ' if(! /(^\s0\s+0\s+0\s+0\s+15965)/omg ) print '
0 0 0 0 5522 -365290 -441287 -78074 -39490 -30774 7921 82126 1391898 1139913 792801 2672554
0 0 0 0 4906 -366163 -441744 -77614 -39125 -31009 7332 81061 1412373 1142806 793817 2837307
0 0 0 0 5000 -300000 -400000 -70000 -30000 -30000 7000 80000
0 0 0 0
$
再次,使用 awk 爆炸
$ perl -ne ' if( /(?=^\s0\s+0\s+0\s+0\s+?)(^.+?)\n/smgo ) 打印"\n$1" else chomp($);打印 "$" ' block_zeros.txt | perl -ne ' if(! /(^\s0\s+0\s+0\s+0\s+15965)/omg ) print ' | awk ' BEGINOFS="\t" for(i=1;i
【讨论】:
以上是关于查找与块格式不匹配的行块的主要内容,如果未能解决你的问题,请参考以下文章
mysql 如何查找同一表中两行之间的差异并列出不匹配的记录? mysql在表中查找不匹配的行