我想遍历一个文件并比较两行,看看它们是否以相同的 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