我有一个包含查询的文件,每个查询以“;”结尾,我想添加一个“COMMIT; BEGIN;”每100个查询。查询可能需要超过1行。
例如:
INSERT INTO table
VALUES(...);
DELETE FROM table WHERE ...;
UPDATE table
SET ...;
所以我想每100次更换一次“;”用“COMMIT; BEGIN;” (我知道我必须添加一个BEGIN;在文件的开头并在最后做一些事情,但这很容易)
我需要在shell脚本中执行此操作,但我不是Linux专家,使用sed或awk更好(文件大小也可以像4GB一样大)?我知道这些命令的基础知识,但我不知道我能不能做我想做的事情......
谢谢!
答案 0 :(得分:1)
如果您可以保证;
位于该行的末尾,或者您并不真正关心具有多个;
的行,那么简单的解决方案(未经测试)是:
awk '/;/{ count+=1 } {print} count==100 { print "COMMIT; BEGIN"; count=0 }'
答案 1 :(得分:1)
我建议不要尝试更换分号。相反,“解析”所有命令并将BEGIN
和COMMIT
放在要提交的命令串周围。这对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