Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在pgdump中匹配多行SQL语句_Sql_Regex_Postgresql_Sed_Grep - Fatal编程技术网

在pgdump中匹配多行SQL语句

在pgdump中匹配多行SQL语句,sql,regex,postgresql,sed,grep,Sql,Regex,Postgresql,Sed,Grep,我有pg_dump 9.5.2版的PostgreSQL数据库转储,其中包含DDL,还包含给定数据库中每个表的INSERT-INTO语句。转储看起来像这样: SET语句\u超时=0; 设置锁定超时=0; 设置客户端_编码='UTF8'; 创建不重要的表( id整数不为空, col1字符变化 ); 创建表( id整数不为空, col2字符不为空, 不重要的字符不为空 ); 插入不重要的_表值(123456,'一些数据拆分为 -多重 -线条 只是为了好玩); 插入重要的_表值(987654321,'一

我有pg_dump 9.5.2版的PostgreSQL数据库转储,其中包含DDL,还包含给定数据库中每个表的
INSERT-INTO
语句。转储看起来像这样:

SET语句\u超时=0;
设置锁定超时=0;
设置客户端_编码='UTF8';
创建不重要的表(
id整数不为空,
col1字符变化
);
创建表(
id整数不为空,
col2字符不为空,
不重要的字符不为空
);
插入不重要的_表值(123456,'一些数据拆分为
-多重
-线条
只是为了好玩);
插入重要的_表值(987654321,'一些重要数据','另一个垃圾拆分为
-行“);
...
--两个表中都有数千个插入项
转储文件非常大,并且是由另一家公司生成的,因此我无法影响导出过程。我需要从此转储创建2个文件:

  • 所有DDL语句(所有不以
    开头的语句插入到
  • 所有
    插入到重要的\u表中
    语句(我只想从转储恢复一些表)
  • 如果所有语句都在单行上,而数据中没有新行字符,那么通过grep创建2个SQL脚本将非常容易,例如:

    grep-v'^INSERT-in.*;$'my_dump.sql>ddl.sql
    grep-o“^INSERT到重要表中。*;$”my_dump.sql>重要_table.sql
    #创建空结构
    psql
    首先,我考虑使用
    grep
    ,但我没有发现如何一次处理多行,然后我尝试了
    sed
    ,但它只返回单行插入。我也曾经找到正确的正则表达式,但我不知道如何将它与
    grep
    sed
    结合起来:

    ^(?(插入)).*--ddl
    ^插入到重要的_表(\s |[:alnum:])*;$--用于插入
    
    我发现了类似的问题,但没有答案。另外,我不介意该解决方案是否可以与
    grep
    sed
    或您建议的任何东西一起使用,但它应该可以在ubuntu18.04.4tls上使用。

    下面是一个基于bash的解决方案,它使用
    perl
    一行程序为后续
    grep
    语句准备SQL转储数据。
    在我的方法中,目标是通过我称为
    prepare.sh
    的脚本在一行上获取一条SQL语句。它变得有点复杂,因为我想在插入数据字符串中容纳分号和引号(这些以及换行符在中间输出中由十六进制代码表示):

    编辑:为了回应@32cupo的评论,下面是一组经过修改的脚本,它避免了使用大数据集进行
    xargs
    (尽管我没有大的转储文件来测试):

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

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


    谢谢你的回答。当我在您的示例中尝试您的代码时,它起作用了,当我在截断的转储中执行它时,但当我在我的转储(9GB,16GB)中尝试它时,它只创建空文件。我试图只运行
    cat large-dump.sql |/prepare.sh
    ,但它什么也不输出。似乎我使用的虚拟机内存不足,无法进行转储,因此我将尝试使用更大的虚拟机,并让您知道。在虚拟机调整大小后,
    xargs:argument line太长
    。你能建议任何改变吗,如何省略xargs?你好@32cupo,我明白了。9GB-16GB是压倒性的xargs。我将检查是否有不同的方法。@32cupo,我已经编辑了答案以提供一组修改过的脚本。
    #!/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' \
    
    #!/bin/bash
    while read -r line; do
        <<<"$line" xargs -I{} echo -e "{}"
    done < <(grep -viE '^(\\\\x0a)*insert into')
    
    #!/bin/bash
    while read -r line; do
        <<<"$line" xargs -I{} echo -e "{}"
    done < <(grep -iE '^(\\\\x0a)*insert into important_table')
    
    ~/$ 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;');