如何添加;在每个“显示创建表”的末尾

时间:2019-07-25 14:56:08

标签: regex python-3.x shell unix hive

所以,我有一个txt文件,其中包含以下内容:

CREATE EXTERNAL TABLE `table1`(
  `tab_id bigint COMMENT 'The unique identifier of thetable')
ROW FORMAT SERDE 
  *
STORED AS INPUTFORMAT 
* 
OUTPUTFORMAT 
  *
LOCATION
  *
TBLPROPERTIES (
  'transient_lastDdlTime'='1556u3ehw27')
CREATE TABLE `table2`(
  `count` bigint)
ROW FORMAT SERDE 
 * 
STORED AS INPUTFORMAT 
  *
OUTPUTFORMAT 
  *
LOCATION
  'hdfs://path/'
TBLPROPERTIES (
  'transient'='15407')

如您所见,在每个表的DDL之后,没有;在它的结尾。我正在尝试编写一个插入;在每个表DDL之后。因此输出应为:

CREATE EXTERNAL TABLE `table1`(
  `tab_id bigint COMMENT 'The unique identifier of thetable')
ROW FORMAT SERDE 
  *
STORED AS INPUTFORMAT 
* 
OUTPUTFORMAT 
  *
LOCATION
  *
TBLPROPERTIES (
  'transient_lastDdlTime'='1556u3ehw27');
CREATE TABLE `table2`(
      `count` bigint)
    ROW FORMAT SERDE 
     * 
    STORED AS INPUTFORMAT 
      *
    OUTPUTFORMAT 
      *
    LOCATION
      'hdfs://path/'
    TBLPROPERTIES (
      'transient'='15407');

我尝试了两种方法。 (1)通过添加DDL创建脚本和python程序。

下面是我的DDL创建.sh脚本,该脚本在数据库的表中运行并为数据库中的所有表生成一个文件。我尝试使用最后一行中显示的cat函数(#cat ...)这样做,但不断收到错误。

 hiveDBName=my_db;

showcreate="show create table "

 showpartitions="show partitions "

 terminate=";"

 tables=`hive -e "use $hiveDBName;show tables;"`

 tab_list=`echo "${tables}"`

 rm -f ${hiveDBName}_all_table_partition_DDL.sql

 for list in $tab_list
 do
        echo "Generating table script for " ${hiveDBName}.${list}
        showcreatetable=${showcreatetable}${showcreate}${hiveDBName}.${list}${terminate}

 done

 echo " ====== Create Tables ======= : " $showcreatetable

##Remove the file
      rm -f ${hiveDBName}_extract_all_tables.txt

      hive -e "use $hiveDBName; ${showcreatetable}" > /home/path/filter_ddls/aa.sql
      grep -v "WARN" /home/path/filter_ddls/aa.sql >/home/path/hive_db_ddls/${hiveDBName}_extract_all_tables.sql
     # cat a1.sql + ";\n\n" >> ${hiveDBName}_extract_all_tables.sql

下面是我的Python程序,但是此方法的输出增加了;只有在跳过某些表的tblproperties之后。

import re
f = open("/home/path/ddl.sql", 'rt', encoding='latin-1').read()

with open("/home/path/new_ddl.sql","w") as output:
    output.write(re.sub(r'(TBLPROPERTIES \(.*?\))', r'\1;', f, flags=re.DOTALL))

有什么想法或建议可以做到这一点?最好是第一个选项(.sh脚本)。

1 个答案:

答案 0 :(得分:3)

在聊天中讨论之后,讨论的两个解决方案如下:

如果您的格式是一致的,并且transient始终出现在需要结尾的';'的行中,则只需要简单的sed替换,例如

sed '/transient/s/$/;/' file

(添加-i选项以就地编辑文件,和/或添加-i.bak进行就地编辑,以保留扩展名.bak的原始文件不变)

如果另一方面,内容可以更改并且transient可能存在或不存在,那么您可以取消TBLPROPERTIES标记,然后向前扫描文件以查找第一个结尾')'之后的TBLPROPERTIES,然后在结尾处添加';'

awk提供了一种更强大的解决方案,因为没有保证TBLPROPERTIES和结束')'之间的行数。 awk下面与一个简单变量look一起用作服务器标志,指示您是否在')'之后TBLPROPERTIES 寻找look=1)或否(look=0)。

例如:

awk -v look=0 '
    /^TBLPROPERTIES/ { look=1 }
    look == 1 {
        if ( sub (/[)]$/,");") )
            look=0
    }1
' file

GNU awk具有gawk -i inplace扩展名,可以像sed一样就地编辑文件,否则,您只需将输出重定向到临时文件,然后复制或移至原始文件名。

无论使用上面的sed还是awk,输出都具有所需的终止';',例如

CREATE EXTERNAL TABLE `table1`(
  `tab_id bigint COMMENT 'The unique identifier of thetable')
ROW FORMAT SERDE
  *
STORED AS INPUTFORMAT
*
OUTPUTFORMAT
  *
LOCATION
  *
TBLPROPERTIES (
  'transient_lastDdlTime'='1556u3ehw27');
CREATE TABLE `table2`(
  `count` bigint)
ROW FORMAT SERDE
 *
STORED AS INPUTFORMAT
  *
OUTPUTFORMAT
  *
LOCATION
  'hdfs://path/'
TBLPROPERTIES (
  'transient'='15407');

如果您还有其他问题,请告诉我。