我有一个很长的词汇表,每行一个单词。有时,有一个重复的单词,出现不止一次或两次。我需要一个简单的代码,它将保留单词的第一个出现,但删除它后面的所有重复项(及其行(。
-
我不想删除任何特殊字符或重新排列任何内容,只需删除单词(每行一个(。保持相同的词序很重要。
-
无论是覆盖原始文件还是保存到新文件,以"更有效"者为准,都没有关系。
-
这是一个由行分隔的列表,而不是一个数组,不以空格或逗号分隔。
-
我没有代码开始,希望用 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