仅保留唯一的行,搜索整个目录

时间:2017-01-05 00:57:20

标签: linux bash shell sh

背景信息

在我的路由器上工作,所以只有60mb的免费ram 我欢迎bash中的答案,但sh将成为我的一天 如果有一个二进制文件,我不介意编译它在我的路由器上运行。

TL; DR

我有一个包含文本文件的目录。

如何确保在所有文件之间,我没有重复的行?

例如,如果a.txtb.txtc.txt包含行apple,则它应仅保留在其中一行中(与哪一行无关)。

如果您需要详细信息

我有一个脚本在同一目录下载多个hosts文件,由dnsmasq使用。

我不想将所有文件合并为一个文件,但要将它们全部删除重复的主机名。

例如,在

y.txt

127.0.0.1    google.com
127.0.0.1    yahoo.com

z.txt

0.0.0.0    apple.com
0.0.0.0    yahoo.com

应该从其中一个中删除包含域yahoo.com的行。

如果该行也存在于另一个文件中,也应该从中删除。

我做了什么

1-将所有文件连接成一个,排序并保留唯一的行 只有一个大文件不是理想的解决方案。

对文件进行2次迭代,将每个文件与剩余文件进行比较 将结果保存在临时文件中,排序,删除重复的行,最后重命名临时文件以替换原始文件 好像我在这里浪费资源。

2 个答案:

答案 0 :(得分:2)

你能试试这个awk吗?它不会在文件中替换。它只是从所有文件中获取第二列的唯一记录

awk '!A[$NF]++' *.txt

答案 1 :(得分:1)

您可以使用sed和临时文件轻松地执行您尝试执行的操作。只需将其中一个文件(例如z.txt)复制到临时文件即可。然后阅读另一个文件中的每一行(例如y.txt)并分为iphost。然后调用sed -i编辑临时文件,删除任何具有匹配$host名称的行。完成后,将z.txt替换为临时文件。

例如:

cp -a z.txt z.tmp                   ## copy z.txt to temp file
while read -r ip host; do           ## read each line in y.txt
    sed -i "/.*$host/d" z.tmp       ## delete $host from temp
done < y.txt
mv -f z.tmp z.txt                   ## replace z.txt with temp

完成后:

$ cat z.txt
0.0.0.0    apple.com

可能还有其他几种方法可以使用awk或简单grep来完成相同的操作,但grep需要读取这两个文件。