如何删除文件中的部分行匹配?

如何删除文件中的部分行匹配?

我想遍历一个文件并比较两行,看看它们是否以相同的 12 个字符开头。如果这样做,我想删除第一行,然后将剩余行与文件中的下一行进行比较,直到比较所有行。

该文件包含目录中已排序的文件列表。可以有两个或多个以相同的 12 个字符开头的文件(始终按顺序)。我只想要最后一张

我在早期的一篇文章中看到了类似的解决方案:

sed '$!N; /\(.*\)\n\1:FOO/D; P;D' file

但我无法修改它以适合我。

答案1

如果您的系统有uniq,您可以使用该-w n选项将比较限制为第一个n每行字符:

uniq -w 12 file.txt

这将返回第一的每场比赛连续出现。

如果你想要最后的每个匹配项连续出现,在处理之前和之后运行文件tac以反转行的顺序uniq

tac file.txt | uniq -w 12 | tac

例子:

[fish/]$ cat fish.txt
Apopterygion_alta.fasta
Apopterygion_oculus.fasta
Oncorhynchus_gorbuscha.fasta
Oncorhynchus_keta.fasta
Oncorhynchus_kisutch.fasta
Oncorhynchus_masou.fasta
Oncorhynchus_nerka.fasta
Oncorhynchus_tshawytscha.fasta
[fish/]$ uniq -w 12 fish.txt
Apopterygion_alta.fasta
Oncorhynchus_gorbuscha.fasta
[fish/]$ tac fish.txt | uniq -w 12 | tac
Apopterygion_oculus.fasta
Oncorhynchus_tshawytscha.fasta

答案2

sed,改编:

sed '$!N; /^\(.\{12\}\).*\n\1/D; P;D'

在除最后 ( $!) 之外的任何行上,它加载下一行 ( N),然后在模式缓冲区中查找重复的 12 个字符(在行开头^,捕获\(\)12 个字符.\{12\},然后匹配任何内容.*,然后是换行符\n,以及捕获的组)再次\1),如果找到,则删除缓冲区中的第一行(D);然后它打印 ( P) 并删除 ( D) 缓冲区中的(剩余)第一行。

$ cat test
foo
barbarbarbar123
barbarbarbar456
doo
$ sed '$!N; /^\(.\{12\}\).*\n\1/D; P;D'  < test
foo
barbarbarbar456
doo

也相当简单awk

$ awk 'NR != 1 && substr($0, 0, 12) != substr(p, 0, 12) {print p} 
     {p=$0} END {print p}' < test
foo
barbarbarbar456
doo

除了第一行 ( NR != 1) 之外,在所有其他行上比较当前行的前 12 个字符$0和字符串p,如果它们不同,则打印p。然后设置p为当前行。在 中,无论如何都END打印。p

相关内容