sort -u 是处理大文件 IP 去重最稳方案,采用外部排序节省内存、保序、兼容 IPv6;awk 容易内存溢出且误判 IPv6 或带端口伪 IP。

用 sort + uniq 处理大文件最稳,别直接上 awk 去重
数万 IP 的文本去重,核心矛盾不是“能不能去”,而是“会不会内存爆掉、会不会顺序乱掉、会不会误判 IPv6”。sort -u 是 Linux 下最可靠的选择——它不依赖内存加载全量数据,而是用外部排序(external sort),边读边归并,对 10 万行 IP 文件通常只占几 MB 内存。
常见错误是写成 awk '!seen[$0]++' ips.txt:IP 行数一过 5 万,awk 的哈希表就可能吃光内存或显著变慢;更糟的是,IPv6 地址里带冒号和方括号(如 [2001:db8::1]),某些 awk 版本会把它们当语法错误或截断处理。
-
sort -u ips.txt > unique_ips.txt—— 简单直接,保留字典序(IPv4 按字符串排,注意192.168.2.1会排在192.168.10.1前面) - 要按真实 IP 数值大小排序 IPv4?用
sort -t. -k1,1n -k2,2n -k3,3n -k4,4n -u ips.txt - 如果原文件有空行或含空格的脏数据,先清洗:
sed '/^[[:space:]]*$/d; s/[[:space:]]*$//' ips.txt | sort -u
遇到 IPv6 或混合格式时,sort 默认行为会出问题
纯 IPv6 地址(如 2001:db8::1)用 sort -u 是安全的;但混着 IPv4 和 IPv6 的文件,sort 会把 192.168.1.1 和 192.168.1.1/32 当作不同字符串——这未必是错,但你要确认业务是否认为带 CIDR 的是独立条目。
真正容易翻车的是带端口或协议前缀的伪 IP,比如 http://10.0.0.1:8080 或 10.0.0.1:22。这些不是标准 IP,sort -u 不会帮你提取主 IP,得先剥离:
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
- 只留 IPv4 主机部分(去掉端口):
sed 's/:.*$//' ips.txt | sort -u - 过滤出合法 IPv4 行(排除空行、域名、URL):
grep -E '^([0-9]{1,3}\.){3}[0-9]{1,3}$' ips.txt | sort -u - IPv6 验证较复杂,建议用
ipcalc或 Python 的ipaddress库做校验,sort本身不校验格式
awk 可以用,但必须加内存和格式兜底
如果你坚持用 awk(比如需要保留首次出现顺序),务必限制输入范围并预处理格式:
- 先确保每行只有 IP,无前后空格:
awk '{$1=$1; print}' ips.txt | awk '!seen[$0]++'(第一个awk压缩空白,第二个去重) - 对超大文件,加
NR 防崩:<code>awk 'NR - 想兼容 IPv6 字面量(含方括号)?
awk -F'[][]' '{ip = $1 ? $1 : $0; if (!seen[ip]++) print}' ips.txt,但这仅适用于[2001:db8::1]这种格式,不覆盖所有情况
去重后还要校验结果是否可信
数万行去重后少了几百行,你得确认是真重复,而不是因为换行符、BOM、不可见字符导致的“假重复”。执行完命令后,快速验证两件事:
- 检查原文件和结果行数差:
wc -l ips.txt unique_ips.txt - 找一个疑似重复的 IP 手动查频次:
grep -c '10.1.1.5' ips.txt,再看它是否真的没出现在unique_ips.txt里 - 用
file命令看编码:file -i ips.txt,如果是utf-8-with-bom,先转码:dos2unix或sed '1s/^\xEF\xBB\xBF//' ips.txt
实际跑下来,sort -u 在机械盘上处理 8 万行 IP 通常不到 2 秒;真正耗时的往往是前期清洗——比如有人把 Excel 导出的 IP 列粘贴进文本,带了制表符或隐藏回车,这种细节不查,去重结果看着对,用起来全错。

















