在文件中每第n次出现一个字符时插入内容

时间:2012-06-05 17:12:05

标签: linux bash shell sed awk

我有一个包含查询的文件,每个查询以“;”结尾,我想添加一个“COMMIT; BEGIN;”每100个查询。查询可能需要超过1行。

例如:


    INSERT INTO table
    VALUES(...);
    DELETE FROM table WHERE ...;
    UPDATE table
    SET ...;

所以我想每100次更换一次“;”用“COMMIT; BEGIN;” (我知道我必须添加一个BEGIN;在文件的开头并在最后做一些事情,但这很容易)

我需要在shell脚本中执行此操作,但我不是Linux专家,使用sed或awk更好(文件大小也可以像4GB一样大)?我知道这些命令的基础知识,但我不知道我能不能做我想做的事情......

谢谢!

4 个答案:

答案 0 :(得分:1)

如果您可以保证;位于该行的末尾,或者您并不真正关心具有多个;的行,那么简单的解决方案(未经测试)是:

awk '/;/{ count+=1 } {print} count==100 { print "COMMIT; BEGIN"; count=0 }'

答案 1 :(得分:1)

我建议不要尝试更换分号。相反,“解析”所有命令并将BEGINCOMMIT放在要提交的命令串周围。这对sed来说相当容易。如果你有这个文件:

$ cat my.sql 
INSERT INTO table VALUES (1);
INSERT INTO table VALUES (2);
INSERT INTO table VALUES (3);
INSERT INTO table VALUES (4);
INSERT INTO table VALUES (5);
INSERT INTO table VALUES (6);
INSERT INTO table VALUES (7);
INSERT INTO table VALUES (8);
INSERT INTO table VALUES (9);
INSERT INTO table VALUES (10);

只需运行此命令:

$ sed -n 'H;${x;s/\([^;]*;\)\{,3\}/BEGIN;&\nCOMMIT;\n\n/g;p}' my.sql 
BEGIN;
INSERT INTO table VALUES (1);
INSERT INTO table VALUES (2);
INSERT INTO table VALUES (3);
COMMIT;

BEGIN;
INSERT INTO table VALUES (4);
INSERT INTO table VALUES (5);
INSERT INTO table VALUES (6);
COMMIT;

BEGIN;
INSERT INTO table VALUES (7);
INSERT INTO table VALUES (8);
INSERT INTO table VALUES (9);
COMMIT;

BEGIN;
INSERT INTO table VALUES (10);
COMMIT;

(为了清楚起见,我使用3作为块的大小。对于“拥抱”100个命令的块,将\{,3\}替换为\{,100\}

它做了什么?

  • 首先,我们禁止使用-n打印行。现在sed只会在我们订购时明确打印它们。

  • 现在,对于每一行,我们使用H将该行附加到保留空间。

  • 在最后一行(地址$),我们执行一个命令块(从{开始到}结束)。第一个命令x交换保留空间的内容(现在包含所有文件)和模式空间。

  • 在此之后,我们用s/// n(0< n< = 3)系列字符(无;)替换后跟;字符串BEGIN;,匹配的命令块(由&表示)和字符串\nCOMMIT;\n\n(使用换行符以提高可读性。

  • 最后,我们使用p打印图案空间的内容。

答案 2 :(得分:0)

如果分号位于该行的末尾:

awk '{print} /;$/ && ! (count++%100) {print "COMMIT; BEGIN;"}' inputfile

如果重要的是精确地计算100个分号并且它们可以在一行中的任何位置,那么它可以完成,但它会变得更复杂。

答案 3 :(得分:0)

这可能适合你(GNU sed);

sed ':a;$!{N;ba};s/^\([^;]*\(;[^\n][^;]*\)*;\s*$\)\{100\}/&\nCOMMIT;BEGIN;/mg' file
相关问题