文本文件清洗入库(MySQL)一例

Posted wzy0623

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文本文件清洗入库(MySQL)一例相关的知识,希望对你有一定的参考价值。

一、需求

        有一批文本文件如下:
numt_qe_0411.txt
numt_qe_0412.txt
numt_qe_0413.txt
numt_qe_0414.txt
...

        每个文件的内容格式如下:
9435446,问题1:,答案1
9575177,问题2? ,答案2
9575177,问题3? ,答案3
...

        可能存在以下几种情况:
1. 文件中有空行
2. 行中可能存在Tab符
3. 可能存在错误折行的情况,如:
9594287,您的性别:,男
9594287,您的年龄: ,70
~80岁
9594287,您的学历:,大专

应为:
9594287,您的性别:,男
9594287,您的年龄: ,70~80岁
9594287,您的学历:,大专


        要求将所有文件内容导入如下结构的 t1 表中:

+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| sdate    | date         | YES  |     | NULL    |                |
| userid   | bigint(20)   | YES  |     | NULL    |                |
| qu_title | varchar(500) | YES  |     | NULL    |                |
| qu_item  | varchar(255) | YES  |     | NULL    |                |
| dstate   | int(255)     | YES  |     | 0       |                |
+----------+--------------+------+-----+---------+----------------+

        第一个逗号之前为一列,对应到字段userid,最后一个逗号后面为第三个字段,对应到字段qu_item;中间内容对应到 字段qu_title;文件名中的日期,导入的时候写到字段 sdate。并且由于资源限制,一次性导入整个一个文件会使得服务器卡死。

二、方案

        先处理文本文件,去掉空行和Tab符号,然后将一个大文件分割成若干小文件。将每个小文件的数据导入一个中间过渡表,之后再将用SQL查询中的字符串和窗口函数处理后的结果插入目标表。

三、实现

1. 创建过渡表

create table t_question (`txt` text) engine=innodb default charset=utf8mb4;

2. 文本文件处理

(1)改成unix格式

cd /data/software/xxqg/
dos2unix *.txt

(2)去掉空行

sed -i '/^$/d' *.txt

(3)Tab符替换为空格

sed -i 's/\\t/ /g' *.txt

(4)分成100000行一个的小文件

mkdir small_file
cd small_file
split -l 100000 -d -a 5 ../numt_qe_0411.txt 04_11_
split -l 100000 -d -a 5 ../numt_qe_0412.txt 04_12_
split -l 100000 -d -a 5 ../numt_qe_0413.txt 04_13_
split -l 100000 -d -a 5 ../numt_qe_0414.txt 04_14_
...

(5)生成SQL命令文件

ls -l | awk 'print "truncate table t_question; load data infile '\\''\\/data\\/software\\/xxqg\\/small_file\\/"$9 "'\\'' into table t_question ;"' | grep 04 > sql_cmd.sql

3. 入库执行内容如下的load_to_table.sh脚本文件

#!/bin/bash
source ~/.bashrc

cat /data/software/xxqg/small_file/sql_cmd.sql|while read line
do
    read mon day <<< `echo $line | awk -F/ 'print $6' | awk -F_ 'print $1,$2'`
    sdate='2022-'$mon'-'$day

    # userid >= 1000000 为正常数据
    # userid < 1000000 为错误折行数据,用lag函数合并到上一行
    # instr(reverse(txt),',') 取得最后一个逗号的位置
    # sleep 1 为缓解负载压力
    
    mysql -u root -p123456 -S /data/18251/mysqldata/mysql.sock -Dtest -e "$line" 
    mysql -u root -p123456 -S /data/18251/mysqldata/mysql.sock -Dtest -e "
    insert into t1 (sdate,userid,qu_title,qu_item)
    select sdate,userid,qu_title,qu_item 
      from (select '$sdate' sdate,substring_index(txt,',',1) userid,substr(txt,instr(txt,',')+1,char_length(txt) - instr(reverse(txt),',')-instr(txt,',')) qu_title,substring_index(txt,',',-1) qu_item from t_question) t  where userid >= 1000000;
    insert into t1 (sdate,userid,qu_title,qu_item)
    select '$sdate' sdate,substring_index(txt,',',1) userid,substr(txt,instr(txt,',')+1,char_length(txt) - instr(reverse(txt),',')-instr(txt,',')) qu_title,substring_index(txt,',',-1) qu_item 
      from (select concat(lag_txt,userid) txt from (select txt,substring_index(txt,',',1) userid,lag(txt,1) over () lag_txt from t_question) t where userid < 1000000) t;
    commit;
    " 
    sleep 1;
done

以上是关于文本文件清洗入库(MySQL)一例的主要内容,如果未能解决你的问题,请参考以下文章

excel数据 入库mysql 和 mysql数据 导入excel文件

数据清洗

python 爬虫之requests+日志+配置文件读取+mysql入库

数据采集 ETL 工具 Elasticsearch-datatran v6.3.9 发布

mysql loaddata加载入库转义符问题

数据库表有内容搜索不出内容