BASH/sed 用于从文本文件中按行分隔的单词列表中删除重复项



我有一个很长的词汇表,每行一个单词。有时,有一个重复的单词,出现不止一次或两次。我需要一个简单的代码,它将保留单词的第一个出现,但删除它后面的所有重复项(及其行(。

  1. 我不想删除任何特殊字符或重新排列任何内容,只需删除单词(每行一个(。保持相同的词序很重要。

  2. 无论是覆盖原始文件还是保存到新文件,以"更有效"者为准,都没有关系。

  3. 这是一个由行分隔的列表,而不是一个数组,不以空格或逗号分隔。

  4. 我没有代码开始,希望用 BASH 解决......

    • sed将是首选

    • grep将是第二选择

    • 第三种选择类似于for循环

例如:文件.txt

apple
banana
car
bicycle
apple
tree
banana
apple
motorcycle

。应该变成:

apple
banana
car
bicycle
tree
motorcycle

我看到了一些 ARRAY 的解决方案,但不是简单的列表,以及通过 python、js 和 C 语言的答案,但没有 BASH。如果已经回答了这个问题,请告诉我在哪里,我很乐意删除这个问题。建议的 dupl. 文章使用awk,这超出了这个问题的范围,尽管它是相关且有用的。

这可能对你有用(GNU sed(:

sed -nr 'G;/^([^n]+n)([^n]+n)*1/!{P;h}' file

在保留空间中保留唯一键列表,如果当前键不在列表中,请打印它并将其添加到列表中。

Pure bash:

#!/bin/bash
declare -g -A lines
while IFS='' read -r line
do
if [[ "${lines["$line"]}" -ne 1 ]]
then
echo "$line"
lines["$line"]=1
fi
done

编辑:如果您将其制作成独立的可执行脚本,则可以使用dedupe.sh < file.txt.如果要在其中对文件名进行硬编码,可以这样做:

while ....
...
done < file.txt

如果您不太关心维护顺序,则可以使用非常简单的:

sort -u inputFileName >outputFileName

这将摆脱所有重复项,在此过程中进行排序。

为了维护基于第一次出现的顺序,它变得更加复杂(并且需要内存(。在awk中使用关联数组是一种方法,如以下示例所示:

pax> cat infile
zanzibar
apple
banana
apple
carrot
banana
sausage
apple
awk '{if(x[$1]==0){x[$1]=1;print}}' infile
zanzibar
apple
banana
carrot
sausage

这种工作方式是,awk第一次看到一个单词时,会存储它看到它的事实并输出单词。该单词的后续实例将无助其事,因为该单词已被标记为已见。

使用排序对文件进行排序后,您可以使用 uniq 删除相邻的重复行。

手册页 uniq

sort unsorted.txt | uniq >> sorted_deduped.txt

最新更新