매우 큰 SQL 파일이 있는데 예를 들어 100000줄마다 "commit;"이라는 새 줄을 추가하고 싶습니다.
이것은 쉽지만 SQL에는 개행 문자가 있는 CLOB 및 BLOB가 포함되어 있습니다.
이 행 내에 새 행이 생성되지 않았는지 확인해야 합니다.
즉, 매 n번째 줄마다 "커밋"을 해야 하지만, 다음 줄이 "INSERT INTO"로 시작하는 경우에만 가능합니다.
입력하다:
INSERT INTO X ..... );
INSERT INTO X ..... );
INSERT INTO X .....foo bar
foo bar foo
bar foo
bar);
INSERT INTO X ..... );
INSERT INTO X ..... );
INSERT INTO X .....foo
bar
foo bar);
INSERT INTO X ..... );
예상 출력(이 예에서는 두 번째 행마다 커밋이 추가된다고 가정):
INSERT INTO X ..... );
INSERT INTO X ..... );
commit;
INSERT INTO X .....foo bar
foo bar foo
bar foo
bar);
INSERT INTO X ..... );
commit;
INSERT INTO X ..... );
INSERT INTO X .....foo
bar
foo bar);
commit;
INSERT INTO xxx ..... );
조언해주셔서 정말 감사드립니다 :)
답변1
commit
아래는 세 번째 삽입마다 붙여넣는 예입니다.
sed '0~2{:a;N;/;$/!ba;s/$/\ncommit;/}'
각 삽입은 줄 끝으로 끝난다고 가정합니다 ;
. (줄 끝에 공백이 있는 줄이 있으면 \s*
그 뒤에 추가해야 할 수도 있습니다.;
논리는 3개의 행을 잡고 ;
끝에 하나가 있는지 확인한 다음 ;
끝에 행을 얻을 때까지 더 많은 행을 연결하는 것입니다. 그런 다음 commit;
.
해당 행을 추가한 후 다음 행을 계속 처리합니다.
필요에 따라 행 수를 자유롭게 조정하세요.
답변2
솔루션은 awk
각 행 세트 n
( n = 3
예제에서는)를 가져와서 "INSERT INTO"로 시작하는 경우 마지막 행 앞에 "COMMIT"를 삽입합니다.
$ awk '{ if (/^INSERT INTO/ && NR%3 == 0) { print "commit;" }; print }' input
답변3
모든 UNIX 시스템의 모든 쉘에 있는 awk의 경우 모든 INSERT 문의 끝에 있을 때 게시한 입력 예에서와 같이 줄 끝에 세미콜론만 있다고 가정합니다.
$ awk '{print} /;$/ && !((++c)%2){print "commit;"}' file
INSERT INTO X ..... );
INSERT INTO X ..... );
commit;
INSERT INTO X .....foo bar
foo bar foo
bar foo
bar);
INSERT INTO X ..... );
commit;
INSERT INTO X ..... );
INSERT INTO X .....foo
bar
foo bar);
commit;
INSERT INTO X ..... );
이 질문에 대해 지나치게 생각할 때의 원래 답변은 다음과 같습니다.
다중 문자 RS에 GNU awk를 사용하고 각 INSERT 문의 끝에 있는 것처럼 줄 끝에 세미콜론만 있다고 가정합니다.
$ awk 'BEGIN{RS=ORS=";\n"} {print} !(NR%2){print "commit"}' file
INSERT INTO X ..... );
INSERT INTO X ..... );
commit;
INSERT INTO X .....foo bar
foo bar foo
bar foo
bar);
INSERT INTO X ..... );
commit;
INSERT INTO X ..... );
INSERT INTO X .....foo
bar
foo bar);
commit;
INSERT INTO X ..... );
그렇지 않으면 모든 UNIX 시스템의 모든 쉘에서 awk를 사용하십시오.
$ awk '/^INSERT/{ if (c++ == 2) {print "commit;"; c=1} } {print} END{if (c == 2) print "commit;"}' file
INSERT INTO X ..... );
INSERT INTO X ..... );
commit;
INSERT INTO X .....foo bar
foo bar foo
bar foo
bar);
INSERT INTO X ..... );
commit;
INSERT INTO X ..... );
INSERT INTO X .....foo
bar
foo bar);
commit;
INSERT INTO X ..... );
END 부분은 N INSERT 문 뒤가 아닌 N+1 INSERT 문 앞에 삽입되기 때문에 필요하며, 입력에 정확히 N INSERT의 배수가 있는 경우를 처리해야 합니다. 예를 들면 다음과 같습니다.
$ cat file
INSERT INTO X ..... );
INSERT INTO X ..... );
INSERT INTO X .....foo bar
foo bar foo
bar foo
bar);
INSERT INTO X ..... );
INSERT INTO X ..... );
INSERT INTO X .....foo
bar
foo bar);
INSERT INTO X ..... );
INSERT INTO X ..... );
END 문이 없으면 마지막을 추가할 수 없습니다 commit;
.
$ awk '/^INSERT/{ if (c++ == 2) { print "commit;"; c=1 } } {print}' file
INSERT INTO X ..... );
INSERT INTO X ..... );
commit;
INSERT INTO X .....foo bar
foo bar foo
bar foo
bar);
INSERT INTO X ..... );
commit;
INSERT INTO X ..... );
INSERT INTO X .....foo
bar
foo bar);
commit;
INSERT INTO X ..... );
INSERT INTO X ..... );
이것으로 우리는 성공했습니다:
$ awk '/^INSERT/{ if (c++ == 2) { print "commit;"; c=1 } } {print}; END{if (c == 2) print "commit;"}' file
INSERT INTO X ..... );
INSERT INTO X ..... );
commit;
INSERT INTO X .....foo bar
foo bar foo
bar foo
bar);
INSERT INTO X ..... );
commit;
INSERT INTO X ..... );
INSERT INTO X .....foo
bar
foo bar);
commit;
INSERT INTO X ..... );
INSERT INTO X ..... );
commit;
물론 commit;
마지막 INSERT 이후에 추가하려는 경우에는 개수에 관계없이 if ( c == 2 )
END에서 제거하고 유지하면 됩니다 print
.