uniq
uniq
命令用于报告或删除文件中的重复行,通常与sort
命令配合使用来处理文本数据。
基本语法
uniq [选项] [输入文件] [输出文件]
主要选项
去重选项
-u, --unique
- 只显示唯一行(出现一次的行)-d, --repeated
- 只显示重复行(出现多次的行)-D, --all-repeated[=METHOD]
- 显示所有重复的行
计数选项
-c, --count
- 在每行前显示出现次数
比较选项
-f, --skip-fields=N
- 跳过前N个字段-s, --skip-chars=N
- 跳过前N个字符-w, --check-chars=N
- 只比较前N个字符-i, --ignore-case
- 忽略大小写
输出选项
-z, --zero-terminated
- 使用NUL字符作为行分隔符
基本使用
简单去重
# 基本去重(需要先排序)
sort file.txt | uniq
# 或者使用sort的-u选项
sort -u file.txt
# 显示去重后的行数
sort file.txt | uniq | wc -l
显示重复行
# 只显示重复的行
sort file.txt | uniq -d
# 显示所有重复的行(包括重复的每一行)
sort file.txt | uniq -D
# 只显示唯一的行(只出现一次的行)
sort file.txt | uniq -u
计数功能
# 显示每行的出现次数
sort file.txt | uniq -c
# 按出现次数排序
sort file.txt | uniq -c | sort -nr
# 找出出现次数最多的行
sort file.txt | uniq -c | sort -nr | head -1
实际应用场景
日志分析
# 统计访问最多的IP地址
cut -d ' ' -f 1 /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -10
# 统计HTTP状态码分布
awk '{print $9}' /var/log/apache2/access.log | sort | uniq -c | sort -nr
# 分析用户代理
awk -F'"' '{print $6}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -10
# 统计访问的文件
awk '{print $7}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -20
系统管理
# 统计系统中的用户shell类型
cut -d: -f7 /etc/passwd | sort | uniq -c
# 分析进程使用情况
ps aux | awk '{print $11}' | sort | uniq -c | sort -nr | head -10
# 统计网络连接状态
netstat -an | awk '{print $6}' | sort | uniq -c
# 分析磁盘使用情况
df -h | tail -n +2 | awk '{print $5}' | sort | uniq -c
数据处理
# 从CSV文件中去除重复记录
sort data.csv | uniq > clean_data.csv
# 统计某列的唯一值数量
cut -d',' -f2 data.csv | sort | uniq | wc -l
# 找出重复的邮箱地址
cut -d',' -f3 contacts.csv | sort | uniq -d
# 统计分类数据
cut -d',' -f1 sales.csv | sort | uniq -c | sort -nr
文本分析
# 统计单词频率
tr '[:space:]' '\n' < document.txt | tr '[:upper:]' '[:lower:]' | sort | uniq -c | sort -nr
# 分析代码中的函数调用
grep -o '\w\+(' *.c | cut -d'(' -f1 | sort | uniq -c | sort -nr
# 统计配置文件中的选项
grep -v '^#' config.conf | cut -d'=' -f1 | sort | uniq -c
高级用法
字段和字符处理
# 跳过第一个字段进行比较
uniq -f 1 file.txt
# 跳过前5个字符进行比较
uniq -s 5 file.txt
# 只比较前10个字符
uniq -w 10 file.txt
# 组合使用:跳过第一个字段和前2个字符
uniq -f 1 -s 2 file.txt
忽略大小写
# 忽略大小写去重
sort file.txt | uniq -i
# 忽略大小写统计
sort file.txt | uniq -i -c
# 示例数据处理
echo -e "Apple\napple\nBanana\nbanana\nApple" | sort | uniq -i -c
不同的重复行显示方式
# 只显示重复行的第一次出现
sort file.txt | uniq -d
# 显示所有重复行
sort file.txt | uniq -D
# 按组显示重复行
sort file.txt | uniq -D --all-repeated=separate
与其他命令结合
与sort的配合
# 排序后去重
sort file.txt | uniq
# 数值排序后去重
sort -n numbers.txt | uniq
# 按第二列排序后去重
sort -k2 file.txt | uniq
# 反向排序后计数
sort -r file.txt | uniq -c
与awk的结合
# 处理CSV文件的特定列
awk -F',' '{print $2}' data.csv | sort | uniq -c
# 复杂的字段处理
awk '{print $1 " " $3}' file.txt | sort | uniq -c
# 条件过滤后去重
awk '$3 > 100 {print $1}' data.txt | sort | uniq
与grep的结合
# 过滤后去重
grep "ERROR" log.txt | sort | uniq -c
# 多文件处理
grep -h "pattern" *.log | sort | uniq -c | sort -nr
# 复杂模式匹配后统计
grep -E "(error|warning|info)" log.txt | awk '{print $3}' | sort | uniq -c
实用脚本示例
日志分析脚本
#!/bin/bash
# log_analyzer.sh
LOG_FILE=${1:-/var/log/apache2/access.log}
echo "=== Apache日志分析报告 ==="
echo "日志文件: $LOG_FILE"
echo "分析时间: $(date)"
echo
echo "=== TOP 10 访问IP ==="
cut -d ' ' -f 1 $LOG_FILE | sort | uniq -c | sort -nr | head -10
echo
echo "=== HTTP状态码分布 ==="
awk '{print $9}' $LOG_FILE | sort | uniq -c | sort -nr
echo
echo "=== TOP 10 访问页面 ==="
awk '{print $7}' $LOG_FILE | sort | uniq -c | sort -nr | head -10
echo
echo "=== 用户代理统计 ==="
awk -F'"' '{print $6}' $LOG_FILE | sort | uniq -c | sort -nr | head -5
数据清理脚本
#!/bin/bash
# data_cleaner.sh
INPUT_FILE=$1
OUTPUT_FILE=$2
if [ -z "$INPUT_FILE" ] || [ -z "$OUTPUT_FILE" ]; then
echo "用法: $0 <输入文件> <输出文件>"
exit 1
fi
echo "清理数据文件: $INPUT_FILE"
# 1. 去除空行
grep -v '^$' $INPUT_FILE > temp1.txt
# 2. 去除重复行
sort temp1.txt | uniq > temp2.txt
# 3. 去除前后空格
sed 's/^[ \t]*//;s/[ \t]*$//' temp2.txt > temp3.txt
# 4. 最终去重
sort temp3.txt | uniq > $OUTPUT_FILE
# 清理临时文件
rm temp1.txt temp2.txt temp3.txt
echo "清理完成!"
echo "原文件行数: $(wc -l < $INPUT_FILE)"
echo "清理后行数: $(wc -l < $OUTPUT_FILE)"
重复数据检查脚本
#!/bin/bash
# duplicate_checker.sh
FILE=$1
FIELD=${2:-1} # 默认检查第一列
if [ -z "$FILE" ]; then
echo "用法: $0 <文件> [字段号]"
exit 1
fi
echo "检查文件 $FILE 第 $FIELD 列的重复数据"
echo "=================================="
# 提取指定字段
if [ "$FIELD" -eq 1 ]; then
COLUMN_DATA=$(awk '{print $1}' $FILE)
else
COLUMN_DATA=$(awk -v field=$FIELD '{print $field}' $FILE)
fi
# 统计重复
DUPLICATES=$(echo "$COLUMN_DATA" | sort | uniq -d)
if [ -z "$DUPLICATES" ]; then
echo "✓ 没有发现重复数据"
else
echo "✗ 发现以下重复数据:"
echo "$COLUMN_DATA" | sort | uniq -c | sort -nr | awk '$1 > 1 {print " " $0}'
echo
echo "重复数据详情:"
for dup in $DUPLICATES; do
echo "值 '$dup' 出现在以下行:"
grep -n "$dup" $FILE | head -5
echo
done
fi
性能优化
大文件处理
# 使用LC_ALL=C加速排序
LC_ALL=C sort large_file.txt | uniq > result.txt
# 分块处理大文件
split -l 1000000 huge_file.txt chunk_
for chunk in chunk_*; do
sort $chunk | uniq > $chunk.clean
done
sort -m chunk_*.clean | uniq > final_result.txt
# 使用内存映射加速
sort --buffer-size=1G large_file.txt | uniq
内存优化
# 限制内存使用
sort -S 500M file.txt | uniq
# 使用临时目录
sort -T /tmp file.txt | uniq
# 压缩临时文件
sort --compress-program=gzip file.txt | uniq
注意事项
- 排序要求: uniq只能处理相邻的重复行,通常需要先sort
- 空行处理: 空行也会被当作可比较的行
- 字符编码: 确保文件编码一致,避免比较错误
- 内存使用: 大文件处理时注意内存消耗
- 字段分隔符: 默认使用空格和制表符作为字段分隔符
相关命令
sort
- 排序文件内容comm
- 比较两个排序文件join
- 连接两个文件awk
- 文本处理工具cut
- 提取字段grep
- 文本搜索
uniq命令是Linux文本处理的重要工具,特别在数据分析和日志处理中发挥重要作用。