整理sql数据
整理sql数据
脚本
#!/usr/bin/bash
cd /path/to/data/dir
#data file 可以换成其他方式,这里写死了
# for file in `ls |grep 'prefix' | grep 'suffix'` 可以换成这种方式,如果文件太多的话
file=(data1.sql data2.sql data.sql) # 写死了
for i in ${file[@]}; do # 遍历文件
#获取表名,将表名放入临时文件(这里是tables)中
cat $i | grep 'CREATE TABLE' | awk -F\` '{print $2}' > tables
cat tables | while read line #遍历文件中的表名
do
echo $line
# 根据表名取inset语句的前5000条数据存入文件中
cat $i | grep 'INSERT INTO `'${line}'`' | head -n 5000 >> data.sql
done
done
rm tables # 删除临时文件
不足
临时文件 tables
原计划不是把表名存入临时文件,而是使用下面的语句把表名保存到变量中,数组。但是没有成功
cat ucr_iom_data.sql | grep 'CREATE TABLE' | awk -F\` '{print $2}'
内存 反复读取文件
当前的脚本会反复读取文件,会导致很大的cpu和io消耗
原本涉及的算法是使用grep
命令,使读取后的文件直接分组(按照表名),而后直接取分组后的前5000条数据。但是,使用grep分组本人还不会
分组的操作类似spark或者flink中的流式api,读取一次文件转换为流后即可一次操作,完成所有功能。
更改-根据表名拆分文件
使用shell命令拆分
#!/usr/bin/bash
path1=/path/to/data/file
cd $path1
file=(data1.sql data2.sql data3.sql)
for i in ${file[@]}; do
cat $i | while read line
do
# echo $line
insert=$(echo $line | awk '{print $1 }' )
if [[ $insert == "INSERT" ]] ; then
#echo $insert ;
name=$(echo $line | awk -F\` '{print $2 }' )
# 这里tables目录应该使用脚本创建,而非手动
echo $line >> ${path1}/tables/${name}.sql
fi
done
done
但是这样处理太慢了,有一个4G的文件(处理这个文件的时候很慢);原因应该是按行处理。
使用sed命令拆分
#!/usr/bin/bash
path1=/path/to/data
cd $path1
file=(data1 data2 data3)
for i in ${file[@]}; do
cat $i | grep 'CREATE TABLE' | awk -F\` '{print $2}' > temp_table_${i}
cat temp_table_${i} | while read line
do
# echo $line
echo "/INSERT INTO \`${line}\`/p"
sed -n -e "/INSERT INTO \`${line}\`/p" $i > ${path1}/data_table/${line}.sql
done
done
使用sed后快多了
附录
原文件的内容说明
原文件是3个,每个文件中包含建表和插入语句。每个文件不止包含一张表,最少的一个文件包含50张表。文件也比较大,最小的文件是300M,而最大的那个由4G。所以手工操作并不会简单多少。
另一种解决方法
使用python或java(本职工作是java开发)处理这个功能
本人近期对shell脚本十分着迷,特别是sed和awk的编辑功能
并且,使用shell可以写更少的代码,而达到相似的功能。
由于本人的shell脚本方面知识的不足,所以感觉十分难写,并且效果/效率不是很好