match pgdump中的多行sql语句

dvtswwa3  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(334)

我有一个postgresql数据库转储,它是由pgïu dump版本9.5.2实现的,其中包含DDL和 INSERT INTO 给定数据库中每个表的语句。转储如下所示:

SET statement_timeout = 0;
SET lock_timeout = 0;
SET client_encoding = 'UTF8';

CREATE TABLE unimportant_table (
    id integer NOT NULL,
    col1 character varying
);

CREATE TABLE important_table (
    id integer NOT NULL,
    col2 character varying NOT NULL,
    unimportant_col character varying NOT NULL
);

INSERT INTO unimportant_table VALUES (123456, 'some data split into
-  multiple
-  lines
just for fun');

INSERT INTO important_table VALUES (987654321, 'some important data', 'another crap split into

-  lines');

...
-- thousands of inserts into both tables

转储文件非常大,而且是由另一家公司生成的,因此我无法影响导出过程。我需要从这个转储创建2个文件:
所有ddl语句(所有不以 INSERT INTO )
全部 INSERT INTO important_table 语句(我只想从dump还原一些表)
如果所有语句都是单行的,数据中没有换行符,那么grep创建2个sql脚本就非常容易了,例如:

grep -v '^INSERT INTO .*;$' my_dump.sql > ddl.sql
grep -o '^INSERT INTO important_table .*;$' my_dump.sql > important_table.sql

# Create empty structures

psql < ddl.sql

# Import only one table for now

psql < important_table.sql

首先我想用 grep 但我没有发现,如何一次处理多行,于是我尝试了 sed 但它只返回单行插入。我也用过https://regex101.com/ 找到正确的正则表达式,但我不知道如何将它与 grep 或者 sed :

^(?!(INSERT INTO)).*$                              -- for ddl
^INSERT INTO important_table(\s|[[:alnum:]])*;$    -- for inserts

我发现类似的问题pcregrep多行sql匹配,但没有答案。另外,我也不介意这个解决方案是否适用于 grep , sed 或者你的建议,但它应该在ubuntu18.04.4tls上工作。

kupeojn6

kupeojn61#

下面是一个基于bash的解决方案 perl 一行程序,为后续的 grep 声明。
在我的方法中,目标是通过我调用的脚本在一行中获得一条sql语句 prepare.sh . 它变得有点复杂,因为我想在insert数据字符串中容纳分号和引号(这些以及换行符在中间输出中由十六进制代码表示):
编辑:为了回应@32cupo的评论,下面是一组修改过的脚本,可以避免 xargs 对于大数据集(尽管我没有大的转储文件来测试它):


# !/bin/bash

perl -pne 's/;(?=\s*$)/__ENDOFSTATEMENT__/g' \
| perl -pne 's/\\/\\\\x5c/g' \
| perl -pne 's/\n/\\\\x0a/g' \
| perl -pne 's/"/\\\\x22/g' \
| perl -pne 's/'\''/\\\\x27/g' \
| perl -pne 's/__ENDOFSTATEMENT__/;\n/g' \

然后,一个单独的脚本(称为 ddl.sh )包括您的 grep 语句(并且在循环的帮助下,只将较小的块(行)馈送到xarg中):


# !/bin/bash

while read -r line; do
    <<<"$line" xargs -I{} echo -e "{}"
done < <(grep -viE '^(\\\\x0a)*insert into')

另一个单独的脚本(称为 important_table.sh )包括您的 grep 插入到重要表中的语句:


# !/bin/bash

while read -r line; do
    <<<"$line" xargs -I{} echo -e "{}"
done < <(grep -iE '^(\\\\x0a)*insert into important_table')

下面是一组正在运行的脚本(请注意,我用一些分号和引号为insert数据添加了香料):

~/$ cat dump.sql
SET statement_timeout = 0;
SET lock_timeout = 0;
SET client_encoding = 'UTF8';

CREATE TABLE unimportant_table (
    id integer NOT NULL,
    col1 character varying
);

CREATE TABLE important_table (
    id integer NOT NULL,
    col2 character varying NOT NULL,
    unimportant_col character varying NOT NULL
);

INSERT INTO unimportant_table VALUES (123456, 'some data split into
-  multiple
-  lines
;just for fun');

INSERT INTO important_table VALUES (987654321, 'some important ";data"', 'another crap split into
-  lines;');

...
-- thousands of inserts into both tables
~/$ cat dump.sql | ./prepare.sh | ./ddl.sh >ddl.sql
~/$ cat ddl.sql
SET statement_timeout = 0;

SET lock_timeout = 0;

SET client_encoding = 'UTF8';

CREATE TABLE unimportant_table (
    id integer NOT NULL,
    col1 character varying
);

CREATE TABLE important_table (
    id integer NOT NULL,
    col2 character varying NOT NULL,
    unimportant_col character varying NOT NULL
);

...
-- thousands of inserts into both tables

~/$ cat dump.sql | ./prepare.sh | ./important_table.sh > important_table.sql
~/$ cat important_table.sql

INSERT INTO important_table VALUES (987654321, 'some important ";data"', 'another crap split into
-  lines;');

相关问题