csv、log、txt文件过大,需要拆分成多个文件

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

日常工作中不免会遇到大文件的csv、日志文件log或者其他txt,但是用wps、文本编辑器打开发现超出行数内容显示范围,导致只显示了一部分内容,于是想着看有什么方法可以快速拆分这些大文件,一开始是想把这些文件导入到oracle数据库的,但是发现如果文件内容不太规范的话导入某些行会报错,最终实践下来发现还是把文件传到linux系统用split或者awk拆分快。


在Linux系统中使用split和awk

一、split

先确认你的文件换行符是'\r\'还是'\n'

bash 复制代码
head -c 500 PB.csv | od -c

文件中有看到 \n(换行符),也有 \r(回车符)。如果没有换行符 \n,只有回车符\r,整个文件可能是一个用 \r 作为行分隔符的文件(老 Mac 风格)

split命令---文件中有看到 \n(换行符)

split命令用于将大文件分割成多个小文件,便于处理或传输。默认按行数分割,也可按大小或自定义规则。

基本语法:

bash 复制代码
split [选项] 输入文件 [输出文件前缀]

常用选项:

  • -l 行数:按指定行数分割
  • -b 大小:按文件大小分割(如-b 10M
  • -d:使用数字后缀而非字母
  • -a 长度:设置后缀长度

示例:

(1)将大文件 PB.csv 按每 1000 行拆分成多个 CSV 文件,输出文件前缀为 output_,并自动添加 .csv 后缀,但是这样直接行数拆分的话只有第一个文件有标题

示例:

bash 复制代码
# 按每1000行分割文件
split -l 1000 PB.csv output_ --additional-suffix=.csv

如果拆分后所有文件都要有标题:使用 split 的 --filter 选项

--filter 允许对每个输出文件执行自定义命令,我们可以将标题行与当前分片内容合并写入最终文件

bash 复制代码
# 1. 提取标题行(保存为临时文件)
head -n 1 PB.csv > header.csv

# 2. 跳过标题行,按 1000 行拆分,并通过 filter 合并标题
tail -n +2 PB.csv | split -l 1000 - output_ --additional-suffix=.csv --filter='cat header.csv - > $FILE'

# 3. 清理临时文件
rm header.csv

split命令---文件中没有换行符 \n,只有回车符\r

如果 CSV 文件中没有换行符 \n,只有回车符 \r,那么直接使用 split -l 1000 将无法正确识别行,因为 split 默认以 \n 作为行分隔符(换行符)。这时候就需要将回车符 \r转换为 \n

(1)直接拆分,只有第一个文件有标题

bash 复制代码
tr '\r' '\n' < ronghang.csv | split -l 1000000 - output_ --additional-suffix=.csv

(2)如果拆分后所有文件都要有标题:使用 split 的 --filter 选项

bash 复制代码
# 1. 提取标题行(注意原文件以 \r 结尾)
head -n 1 PB.csv | tr '\r' '\n' > header.csv

# 2. 将整个文件的 \r 转为 \n,跳过标题行,按 1000 行拆分并添加标题
tail -n +2 PB.csv | tr '\r' '\n' | \
split -l 1000 - output_ --additional-suffix=.csv \
  --filter='cat header.csv - > $FILE'

# 3. 清理临时文件
rm header.csv

二、awk命令

awk是一种强大的文本处理工具,支持模式扫描和语言处理,常用于数据提取、报表生成等。

基本结构:

bash 复制代码
awk '模式 {动作}' 输入文件

常用功能:

  • 按列处理:$1表示第一列
  • 内置变量:NR(行号)、NF(当前行列数)
  • 数学运算:直接在动作中计算
  • 条件判断:支持if/else等逻辑

示例:

bash 复制代码
# 打印文件第一列和第三列
awk '{print $1,$3}' data.txt

# 过滤第二列大于100的行
awk '$2 > 100 {print $0}' records.txt

# 计算列总和
awk '{sum += $1} END {print sum}' numbers.txt

# 使用分隔符(默认空格)
awk -F',' '{print $2}' csv_file.csv

组合使用案例,拆分大文件

将大日志文件按每月分割拆分处理:

bash 复制代码
# 1. 预创建文件并写入标题(可选,防止某个月没数据导致文件不存在)
# 注意:这里假设你的年份范围是 2024-2026
head -n 1 PB.csv | while read line; do
    for year in 2024 2025 2026; do
        for month in 01 02 03 04 05 06 07 08 09 10 11 12; do
            echo "$line" > "${year}_${month}.csv"
        done
    done
done

# 2. 使用 awk 处理数据
awk '
NR==1 { next } # 跳过标题行
{ 
    # 获取第一列并清洗
    raw_date = $1;
    gsub(/"/, "", raw_date);
    
    # 提取年月 (假设格式 yyyymmdd)
    year = substr(raw_date, 1, 4);
    month = substr(raw_date, 5, 2);
    
    # 校验年份和月份
    if (year ~ /^[0-9]{4}$/ && month ~ /^[0-9]{2}$/) {
        # 直接拼接文件名:例如 2024_04.csv
        file = year"_"month".csv";
        
        print >> file;
        close(file);
    }
}' PB.csv

按每季度拆分

bash 复制代码
# 1. 提取并保存CSV文件的标题行到每个可能生成的季度文件中
head -n 1 PB.csv | while read line; do
    for year in 2024 2025 2026; do # 根据你的数据年份范围修改
        for q in 1 2 3 4; do
            echo "$line" > "${year}_Q${q}.csv"
        done
    done
done

# 2. 使用awk处理所有数据行,并追加(>>)到对应的文件中
awk -F',' 'NR > 1 {
    # 去除第一列的双引号和回车符
    gsub(/["\r]/, "", $1);
    
    year = substr($1, 1, 4);
    month = substr($1, 5, 2);
    
    # 确保月份是有效数字
    if (month ~ /^[0-9]+$/) {
        q = int((month - 1) / 3) + 1;
        file = year "_Q" q ".csv";
        
        # 关键:使用 >> 进行追加,而不是 > 覆盖
        print >> file;
        close(file);
    }
}' PB.csv

注意事项:

  • split生成的文件默认以xaa/xab命名,可用--additional-suffix指定后缀
  • awk支持正则表达式和复杂逻辑,可编写多行脚本
  • 处理CSV时注意用-F指定分隔符
  • 大数据量时建议先用split分割再处理

总结

提示:这里对文章进行总结:

例如:以上就是今天要讲的内容,本文仅仅简单介绍了split、awk拆分大文件的使用,更多用法请查找相关资料学习。

相关推荐
HalvmånEver1 小时前
MySQL 使用 C 语言连接
linux·数据库·学习·mysql
南境十里·墨染春水1 小时前
linux学习进展 libevent
linux·运维·学习
开开心心就好1 小时前
直接减少蓝光辐射的专业护眼工具
linux·运维·服务器·智能手机·excel·java-rabbitmq·sdkman
Shadow(⊙o⊙)2 小时前
进程分析—从操作系统到Linux内核深入
linux·运维·服务器·开发语言·网络·c++·后端
辞旧 lekkk10 小时前
【Qt】信号和槽
linux·开发语言·数据库·qt·学习·mysql·萌新
liuhuizuikeai12 小时前
可视化门禁---Linux/Qt+SqLite篇
linux·运维·qt
初願致夕霞13 小时前
基于系统调用的Linux网络编程——UDP与TCP
linux·网络·c++·tcp/ip·udp
charlie11451419115 小时前
嵌入式Linux驱动开发——新 API 字符设备驱动完整教程 - 从设备结构体到应用测试
linux·运维·驱动开发
消失的旧时光-194316 小时前
C语言对象模型系列(四)《Linux 内核里的 container_of 到底是什么黑魔法?》—— 一篇讲透 Linux 内核的“对象模型”核心技巧
linux·c语言·算法