0

0

如何在Linux中去重数据 Linux uniq相邻行处理

P粉602998670

P粉602998670

发布时间:2025-08-30 10:02:01

|

524人浏览过

|

来源于php中文网

原创

答案:在Linux中使用uniq命令去重需先排序处理非相邻重复行,核心方法是结合sort与uniq实现全局去重。通过sort将相同行聚拢,再用uniq去除相邻重复,配合-c、-d、-u、-i等选项可实现统计、筛选重复或唯一行,使用-f、-s可跳过字段或字符进行部分比较,大规模数据时可通过优化sort参数或改用awk、Python等工具提升性能。

如何在linux中去重数据 linux uniq相邻行处理

在Linux中对数据进行去重,尤其是处理相邻重复行,

uniq
命令无疑是你的首选工具。它设计之初就是为了高效地移除或识别文本流中连续出现的重复行。但如果你的重复行并非相邻,那么通常需要先进行排序,将所有相同的行聚集在一起,然后才能有效地利用
uniq
进行处理。简单来说,
uniq
负责处理“紧挨着”的重复,而全局去重则需要
sort
的配合。

解决方案

要处理Linux中的数据去重,特别是利用

uniq
,核心思想是理解它只处理相邻行。这意味着如果你的数据是乱序的,比如:

apple
banana
apple
cherry
banana

直接对它运行

uniq
不会有任何效果,因为
apple
banana
之间都被不同的行隔开了。正确的做法,尤其对于非相邻重复,是先用
sort
命令将所有相同的行排在一起,然后再管道给
uniq

基本用法:

  1. 移除相邻重复行:

    cat your_file.txt | uniq

    或者直接

    uniq your_file.txt

    这只会移除紧邻的重复行。

  2. 移除所有重复行(包括非相邻的):

    sort your_file.txt | uniq

    这是最常见的全面去重组合。

    sort
    会将所有相同的行排在一起,然后
    uniq
    就能轻松地将它们合并成一行。

uniq
的常用选项:

  • -c
    (count): 在每行前面显示该行重复的次数。
    sort your_file.txt | uniq -c
  • -d
    (duplicated): 只显示重复的行(每种重复只显示一次)。
    sort your_file.txt | uniq -d
  • -u
    (unique): 只显示不重复的行。
    sort your_file.txt | uniq -u
  • -i
    (ignore-case): 忽略大小写进行比较。
    sort -f your_file.txt | uniq -i

    注意,

    sort
    也有
    -f
    选项用于忽略大小写排序,两者结合使用效果更好。

  • -f N
    (skip-fields): 跳过前N个字段进行比较。字段默认以空格分隔。
    # 假设文件内容是 "ID Name"
    # 101 apple
    # 102 banana
    # 101 apple
    sort -k 2,2 your_file.txt | uniq -f 1
    # 这会根据第二个字段(Name)去重,忽略第一个字段(ID)
  • -s N
    (skip-chars): 跳过前N个字符进行比较。
    # 假设文件内容是 "PREFIX_data1" 和 "PREFIX_data1"
    # 如果只想比较 "data1",可以跳过 "PREFIX_" 的长度
    sort your_file.txt | uniq -s 7

这些选项的组合使用能让你在去重时拥有极高的灵活性和精确度。

为什么
uniq
只能处理相邻重复行?以及如何应对非相邻重复?

这其实是个很经典的误区,或者说,是

uniq
命令设计哲学的一个核心点。
uniq
的工作机制相当直观,它本质上就是比较当前行和前一行。如果这两行完全相同,它就会“忽略”掉当前行,只输出前一行。这个过程不断重复,直到遇到一个与前一行不同的行,然后输出这个新行。所以,如果你的数据像这样:

foo
bar
foo
baz

uniq
看到第一个
foo
,然后看到
bar
,它们不同,于是输出
foo
bar
。接着看到第二个
foo
,它与
bar
不同,所以
foo
也被输出了。最终结果是所有行都原样输出,因为没有任何相邻的重复。

我的经验是,要应对非相邻重复,你几乎总是需要

sort
命令的帮助。
sort
的任务就是将所有相同的行聚集在一起,形成一个连续的块。比如,上面的数据经过
sort
之后会变成:

bar
baz
foo
foo

这时候,

uniq
就能派上用场了。它会看到第一个
foo
,然后看到第二个
foo
,发现它们是相邻的重复,于是只输出一个
foo
。最终结果就是:

bar
baz
foo

应对策略和一些注意事项:

  1. sort | uniq
    是标准组合:
    这几乎是处理文本文件全局去重的黄金法则。它简单、高效,并且在绝大多数情况下都能满足需求。
    cat my_data.log | sort | uniq > deduped_data.log
  2. sort
    的性能考量:
    对于非常大的文件,
    sort
    可能会占用大量的内存和磁盘I/O。你可以使用
    sort -T /tmp
    来指定一个临时目录,避免填满默认的
    /tmp
    ,或者
    sort -S 50%
    来告诉它使用多少内存(例如,使用50%的可用内存)。
  3. 排序键的指定: 有时候你只想根据行的某个部分进行去重,而不是整行。
    sort -k
    uniq -f
    uniq -s
    就能派上用场。例如,如果你有一个CSV文件,想根据第二列去重,但保留第一列,你可以这样:
    # 假设文件是 "ID,Name"
    # 1,Apple
    # 2,Banana
    # 1,Apple
    sort -t',' -k2,2 my_csv.txt | uniq -f 1 -s 1 # -s 1 是为了跳过逗号

    这里

    -t','
    指定逗号为分隔符,
    -k2,2
    表示按第二列排序。
    uniq -f 1
    表示跳过第一个字段(ID),从第二个字段开始比较。
    uniq -s 1
    略微有点复杂,因为它跳过的是字符,这里是为了跳过逗号后的第一个字符,这可能需要根据实际数据格式调整。更精确的去重往往需要结合
    awk
    等工具。

理解

uniq
的“相邻”限制是掌握其强大功能的第一步。一旦你掌握了
sort
uniq
的协作,你会发现它们在日常数据处理中是多么不可或缺。

人民网AIGC-X
人民网AIGC-X

国内科研机构联合推出的AI生成内容检测工具

下载

uniq
命令有哪些高级用法,能帮我更精细地控制去重过程?

当我们说

uniq
的高级用法,其实更多的是指如何巧妙地利用它的各种选项来应对复杂的去重需求,而不仅仅是简单的移除重复。这就像是给你的工具箱里又多添了几把不同形状的螺丝刀,让你能拧开各种奇形怪状的螺丝。

  1. 统计与识别:

    uniq -c
    uniq -d
    /
    uniq -u

    • uniq -c
      (计数):
      这恐怕是除了基本去重外最常用的功能了。它不仅去重,还会在每行前面加上该行出现的次数。这对于分析数据频率非常有用。
      # 统计访问日志中每个IP出现的次数
      cat access.log | awk '{print $1}' | sort | uniq -c | sort -nr

      sort -nr
      会将结果按数字降序排列,让你一眼看出哪些IP访问最频繁。我个人觉得,这个组合在日志分析时简直是神器。

    • uniq -d
      (只显示重复行):
      如果你只想知道哪些行是重复的,并且每种重复只显示一次,
      -d
      就派上用场了。它不会显示那些只出现一次的行。
      # 找出文件中所有重复的行(每种重复只显示一次)
      sort your_file.txt | uniq -d
    • uniq -u
      (只显示唯一行):
      相反,如果你只对那些在文件中只出现过一次的行感兴趣,
      -u
      是你的朋友。
      # 找出文件中所有只出现过一次的行
      sort your_file.txt | uniq -u

      这个在数据清洗中很有用,比如找出某个列表里真正的“独苗”。

  2. 忽略细节:

    uniq -i
    (忽略大小写)

    • 在处理一些非规范化的文本数据时,大小写不一致是个常见问题。例如,“Apple”和“apple”可能被认为是不同的行。
      -i
      选项让
      uniq
      在比较时忽略这些差异。
      # 忽略大小写去重
      sort -f your_list.txt | uniq -i

      注意,为了让

      uniq -i
      真正有效,通常也需要
      sort -f
      (或
      sort --ignore-case
      )来确保大小写不一致的行也能被排到一起。

  3. 部分比较:

    uniq -f N
    (跳过字段) 和
    uniq -s N
    (跳过字符)

    • 这两个选项允许你定义
      uniq
      比较的“范围”。它们非常强大,但需要你对数据结构有清晰的理解。
    • uniq -f N
      跳过前
      N
      个字段。字段默认以空格或制表符分隔。
      # 假设文件内容是:
      # 2023-01-01 user1 login_success
      # 2023-01-01 user2 login_fail
      # 2023-01-02 user1 login_success
      # 如果我们只想根据“user”和“login_status”去重,忽略日期
      # 先按user和status排序,然后跳过第一个字段(日期)
      cat log.txt | sort -k2,2 -k3,3 | uniq -f 1

      这里

      sort -k2,2 -k3,3
      是按第二和第三个字段排序。
      uniq -f 1
      告诉
      uniq
      在比较时忽略行的第一个字段。

    • uniq -s N
      跳过前
      N
      个字符。这在你需要基于行的特定起始部分去重时很有用,比如所有以特定前缀开头的行。
      # 假设文件内容:
      # MSG_ERROR: Disk full
      # MSG_INFO: System started
      # MSG_ERROR: Disk full
      # 如果我们只想根据冒号后的内容去重
      sort messages.log | uniq -s 11 # 跳过 "MSG_ERROR: " 或 "MSG_INFO: "

      这里

      11
      是 "MSG_ERROR: " 的长度。这种用法需要你对前缀长度有准确的把握。

这些高级选项的组合使用,能够让你在面对各种去重场景时,都能找到一个优雅且高效的解决方案。有时候,你可能还需要配合

cut
awk
等工具来预处理数据,以更好地适配
uniq
的比较逻辑。

处理大规模数据时,
uniq
的性能瓶颈和替代方案有哪些?

处理大规模数据时,任何命令行工具都可能遇到性能瓶颈,

uniq
也不例外。它的主要瓶颈往往不是
uniq
本身,而是它前置的
sort
命令。当文件大小达到几十GB甚至上TB时,
sort
需要将整个文件读入、排序,这会消耗大量的内存(如果文件能完全放入内存)或进行大量的磁盘I/O(如果需要使用临时文件)。

uniq
的性能瓶颈:

  1. sort
    的内存与I/O:
    这是最主要的瓶颈。
    sort
    在处理大文件时,如果内存不足以容纳所有数据,它会使用磁盘上的临时文件进行分块排序和合并。这个过程可能非常慢,尤其是在机械硬盘上。
  2. 默认的区域设置 (Locale):
    sort
    命令的默认行为受
    LANG
    LC_ALL
    等环境变量影响。不同的区域设置可能导致不同的排序规则,这有时会增加排序的计算复杂度,虽然通常影响不大,但在极端情况下也值得考虑。
  3. 管道开销: 虽然
    sort | uniq
    这种管道操作通常很高效,但在极其庞大的数据流中,进程间通信的开销也可能累积。

替代方案和优化策略:

对于大规模数据去重,我们通常会考虑以下几种策略:

  1. 优化

    sort
    命令:

    • 指定临时目录: 使用
      sort -T /path/to/fast/disk
      将临时文件放到读写速度更快的磁盘上(比如SSD),或者是一个有足够空间的磁盘分区,避免填满
      /tmp
    • 增加内存使用: 使用
      sort -S 50%
      sort -S 4G
      来告诉
      sort
      使用更多的内存。这可以减少磁盘I/O,但要确保你的系统有足够的空闲内存,否则可能导致系统不稳定。
    • 并行排序: GNU
      sort
      现代版本已经支持多线程,但其并行能力主要体现在合并阶段。对于非常大的文件,可以考虑将文件分割成小块并行排序,再合并。
  2. 使用

    awk
    进行去重:
    awk
    凭借其关联数组(associative arrays)特性,可以非常高效地实现去重,尤其是在不需要排序的场景下,或者当去重逻辑比较复杂时。

    awk '!a[$0]++' your_large_file.txt > deduped_with_awk.txt

    这个

    awk
    命令的工作原理是:它将每一行作为关联数组
    a
    的键。
    a[$0]++
    会在每次遇到新行时将其值加1。
    !a[$0]++
    的意思是,如果
    a[$0]
    的值是0(即第一次遇到这行),那么表达式为真,
    awk
    就会打印这行。之后再遇到相同的行时,
    a[$0]
    的值就不是0了,表达式为假,该行就不会被打印。
    awk
    的优势:
    不需要预先排序,对于内存能容纳所有唯一行的场景,性能极佳。
    awk
    的局限:
    如果唯一行的数量非常庞大,以至于关联数组无法完全载入内存,
    awk
    可能会耗尽内存并崩溃。在这种情况下,
    sort | uniq
    依赖磁盘的策略反而更稳健。

  3. 使用

    perl
    python
    脚本:
    对于更复杂的去重逻辑,或者当数据量非常大且
    awk
    不够灵活时,
    perl
    python
    提供了更强大的编程能力。它们也可以使用哈希表(类似于
    awk
    的关联数组)来实现去重。 Python 示例:

    seen = set()
    with open('your_large_file.txt', 'r') as infile, \
         open('deduped_with_python.txt', 'w') as outfile:
        for line in infile:
            if line not in seen:
                outfile.write(line)
                seen.add(line)

    这与

    awk
    的原理类似,将已见过的行存储在一个
    set
    中。
    set
    的查找效率非常高。 优势: 极高的灵活性,可以实现任何复杂的去重逻辑(例如,根据JSON字段去重、根据正则表达式匹配部分内容去重等)。 局限: 同样受限于内存,如果唯一行过多,
    set
    或哈希表会占用大量内存。

  4. 分布式处理框架: 对于真正意义上的“海量数据”(TB级别以上),单机工具的局限性就显现出来了。这时,你需要考虑使用分布式处理框架,如 Apache Hadoop (MapReduce)Apache Spark。这些框架天生就是为处理大规模数据集而设计的,它们可以将数据分布到集群中的多台机器上进行并行排序和去重。

    • MapReduce 思路: Map阶段将每行作为键值对
      (line, 1)
      输出;Reduce阶段对每个键(即每行)只输出一次。
    • Spark 思路: 利用RDD的
      distinct()
      方法,或者
      groupByKey().mapValues(lambda x: 1)
      等操作。

总的来说,对于日常的大部分去重任务,

sort | uniq
组合是首选。当遇到性能瓶颈时,先尝试优化
sort
的参数。如果内存允许且不需要排序,
awk
是一个极佳的替代品。而对于极端规模或复杂逻辑,编程语言或分布式框架才是最终的解决方案。选择哪种方法,取决于你的数据量、去重规则的复杂性以及可用的计算资源。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

751

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

636

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

758

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

618

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1262

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

547

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

577

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

706

2023.08.11

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

36

2026.01.14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
进程与SOCKET
进程与SOCKET

共6课时 | 0.3万人学习

PHP入门到实战消息队列RabbitMQ
PHP入门到实战消息队列RabbitMQ

共22课时 | 1.3万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 2.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号