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

注意事项

  1. 排序要求: uniq只能处理相邻的重复行,通常需要先sort
  2. 空行处理: 空行也会被当作可比较的行
  3. 字符编码: 确保文件编码一致,避免比较错误
  4. 内存使用: 大文件处理时注意内存消耗
  5. 字段分隔符: 默认使用空格和制表符作为字段分隔符

相关命令

  • sort - 排序文件内容
  • comm - 比较两个排序文件
  • join - 连接两个文件
  • awk - 文本处理工具
  • cut - 提取字段
  • grep - 文本搜索

uniq命令是Linux文本处理的重要工具,特别在数据分析和日志处理中发挥重要作用。

powered by Gitbook© 2025 编外计划 | 最后修改: 2025-07-28 12:42:41

results matching ""

    No results matching ""