一日,包工头让我们整理一个归纳文档;主要是现在生产上所有表的建表语句都存在一个文件中,这样,不利于版本更新的控制,所以要把这个文件拆分为一个建表语句一个文件,且要以表名作为文件名,粗略估计一下,有四千多张表。
OK,目标明确;第一反应想到的肯定是用Linux 脚本拆分,几经翻阅资料,上网查询终于写出来一种方法;
先上干货
#!/usr/bin/bash
myfile=/var/db/hmoc/1216/ddl.sql #target file path
line=`sed -n '/location/=' $myfile` #get line numbers about keywords
endline=0
for no in ${line[*]}
do
let startline=endline+1
endline=${no}
echo `sed -n "${endline}, ${endline}p" $myfile` | while read para1 filename1
do
filename2=${filename1##*/}
filename3=${filename2%\'*}
sed -n "${startline}, ${endline}p" ${myfile} > ${filename3}.sql
done
done
首先分析:既然要拆分建表语句为单表单文件,首先想到使用split 拆分,然后就是sed ,sed 中有一个类似指定范围打印的功能。因为比较熟悉所以就选择了sed。还有一个问题就是如何完整的拆分出每个表的语句呢,按固定的行数肯定不行,但是sed 打印的时候必须指定行的范围,那就需要关键字(keyword),需要根据keywors 找出行号,再把行号处理后打印输出内容至指定的小文件即可。
涉及知识点:
① 也是最重要的,三剑客之一的sed 命令(主要使用的是查找行号和打印的功能)
② 知道如何根据指定字符截取字符串(是作为文件名使用)
③ 知道${#line[@]} ${line[*]}的使用
下面代码为测试文件中的一段(hive 的建表语句)
create table if not exists test_tab_card(
agmt_no string,
......
agmt_serial_no string
)
comment '测试表'
row format delimited fields terminated by '\001' lines terminated by '\\N'
stored as parquet
location '/user/hive/warehouse/testdb.db/test_tab_card';
create table ......
命令解析:
line=`sed -n '/location/=' $myfile`
首先定义line 接收sed 的结果,这里sed 返回的是关键字location 所在的行号,是文件中所有包含keywords 的行号
for 循环中的 ${line[*]} 是上面sed 的结果的所有组合集(行号的组合集)
其中while 的部分主要是为了获得文件名,即是为了截取出表名。这里根据个人所需;因为我的建表语句为hive 的建表语句,所以这里可能和各位的截取限制会不一样。
主要涉及 filename2=${filename1##*/} 和 filename3=${filename2%\'*} ;
filename2=${filename1##*/} --为剔除最后一条 / 及其左边的字符串
filename3=${filename2%\'*} --为剔除最后一个 ' 及其右边的字符串(这里是单引号,须加反斜杠转译)
这样就得到了表名。
PS:如果你的限制不一样,请自行百度修改,或者与我联系可予以帮助
最后再使用sed 命令 截取指定的范围打印输入,然后将输出结果重定向到以表名命名的文件中即可!!!
打工搞成 😄 😄 😄 😄
(代码为手工敲打,本地未测试,如果有误,请联系小砖工)
如有些许帮助,请点个赞给我些加油!
^-^