我有一个文件,其中字符串由特殊字符串(不是逗号或分隔符)分隔,例如<vvv>
. 我想检查第一个字段中的所有字符串是否都是唯一的。如果发现同一字段的重复行,我想删除任何重复的行(保留第一次出现)。
例子:
aaa<vvv>bbb<vvv>ccc
xxx<vvv>yyy<vvv>zzz
aaa<vvv>new<vvv>new2
111<vvv>222<vvv>333
我想得到:
aaa<vvv>bbb<vvv>ccc
xxx<vvv>yyy<vvv>zzz
111<vvv>222<vvv>333
我们删除aaa<vvv>new<vvv>new2
是因为aaa
已经出现了。
我不喜欢我们awk
,除非它是唯一的解决方案。它的语法对我来说有点复杂,因为我不熟悉 Linux。
不用
awk
太多:这仅用于
awk
将行号插入<
到原始数据中。我们这样做是为了能够跟踪原始行的顺序。我们将<
其用作行号和行的其余部分之间的分隔符,因为这也显示为原始第一个字段和行的其余部分之间的分隔符。在
awk
用于插入行号的管道的第一阶段之后,数据将如下所示管道的下一步在第二个字段(第一个原始字段)上对其进行排序,删除重复项。结果将是
第二个
sort
通过对第一个字段上的行进行数字排序来恢复原始行顺序,我们得到然后
cut
从第一个字段(和插入的分隔符)中删除数字。一个完全不使用就给出有序输出的解决方案
awk
看起来像这本质上是上述管道中的第二步,它在第一个字段上对文件进行排序,同时删除重复项。
一个
awk
解决方案看起来像这会将第一个字段作为键存储在一个名为的关联数组中
seen
,并后递增关联的值。如果给定键的数组中的值为零(即,以前没有见过第一个字段),则打印该行。或等效地既不
awk
也不cut
,但与sed
:但这非常笨拙。@Kusalananda 的最后一个(基于 awk 的)解决方案要好得多。
只是为了教学,
sed
上面的前两个块相当于 Kusalananda 更紧凑的awk
cmd :sed '=' file
, 打印行号以供将来订购sed 'N;s/\n/</'
, 在模式空间中附加下一个输入行(即“连接当前行和下一行”)并将行尾替换\n
为<
.第三个也是最后一个
sed
花絮,sed 's/^[0-9]*<//'
替换行号和放在每行开头的“<”,什么都没有。有关更多详细信息
sed
,$ info sed
请在您的控制台中发布。使用 GNU sed 我们可以完成给定的任务:
将第一个字段存储在保持空间中,并将其与当前行的第一个字段进行比较。只有当它们不同时,才更新保持,同时打印当前行。
尝试了以下2种方法
输出