How can I add some text after some sequence of text if this sequence matches certain criteria using Shell...
I want to add a statement just after the text matching the conditions mentioned in a shell script,
Below is my sample File(SQL File) :
begin
AFFECTED_ROWS := 0;
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
DELETE FROM table_name
WHERE condition;
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
end;
I will take this file and perform below transformation,
Once I see any of below Text in sequence
1: "UPDATE ... SET ...;"
2: "DELETE ... FROM ...;"
3: "INSERT ... INTO ...;"
4: "MERGE ... INTO ... [WHEN MATCHED THEN | WHEN NOT MATCHED] ... [UPDATE|INSERT|DELETE] ... ;"
I need to add 1 extra row just after the semicolon
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
So My new file will look like something below
begin
AFFECTED_ROWS := 0;
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
DELETE FROM table_name
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
end;
I tried finding and implementing the approach in the scope of PLSQL but didn't find any generic way possible to get no of rows affected, so I thought
of text parsing but I don't know much about awk or sed.
For now what I was trying to do something like below:
sed '/Patterns Go Here/a AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;' temp.sql
So pattern may have conditions mentioned above
shell-script shell awk grep
add a comment |
I want to add a statement just after the text matching the conditions mentioned in a shell script,
Below is my sample File(SQL File) :
begin
AFFECTED_ROWS := 0;
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
DELETE FROM table_name
WHERE condition;
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
end;
I will take this file and perform below transformation,
Once I see any of below Text in sequence
1: "UPDATE ... SET ...;"
2: "DELETE ... FROM ...;"
3: "INSERT ... INTO ...;"
4: "MERGE ... INTO ... [WHEN MATCHED THEN | WHEN NOT MATCHED] ... [UPDATE|INSERT|DELETE] ... ;"
I need to add 1 extra row just after the semicolon
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
So My new file will look like something below
begin
AFFECTED_ROWS := 0;
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
DELETE FROM table_name
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
end;
I tried finding and implementing the approach in the scope of PLSQL but didn't find any generic way possible to get no of rows affected, so I thought
of text parsing but I don't know much about awk or sed.
For now what I was trying to do something like below:
sed '/Patterns Go Here/a AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;' temp.sql
So pattern may have conditions mentioned above
shell-script shell awk grep
Welcome to Unix & Linux. ;-) You might be better off on our sister site Database Administrators...
– Fabby
Oct 24 at 23:00
add a comment |
I want to add a statement just after the text matching the conditions mentioned in a shell script,
Below is my sample File(SQL File) :
begin
AFFECTED_ROWS := 0;
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
DELETE FROM table_name
WHERE condition;
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
end;
I will take this file and perform below transformation,
Once I see any of below Text in sequence
1: "UPDATE ... SET ...;"
2: "DELETE ... FROM ...;"
3: "INSERT ... INTO ...;"
4: "MERGE ... INTO ... [WHEN MATCHED THEN | WHEN NOT MATCHED] ... [UPDATE|INSERT|DELETE] ... ;"
I need to add 1 extra row just after the semicolon
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
So My new file will look like something below
begin
AFFECTED_ROWS := 0;
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
DELETE FROM table_name
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
end;
I tried finding and implementing the approach in the scope of PLSQL but didn't find any generic way possible to get no of rows affected, so I thought
of text parsing but I don't know much about awk or sed.
For now what I was trying to do something like below:
sed '/Patterns Go Here/a AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;' temp.sql
So pattern may have conditions mentioned above
shell-script shell awk grep
I want to add a statement just after the text matching the conditions mentioned in a shell script,
Below is my sample File(SQL File) :
begin
AFFECTED_ROWS := 0;
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
DELETE FROM table_name
WHERE condition;
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
end;
I will take this file and perform below transformation,
Once I see any of below Text in sequence
1: "UPDATE ... SET ...;"
2: "DELETE ... FROM ...;"
3: "INSERT ... INTO ...;"
4: "MERGE ... INTO ... [WHEN MATCHED THEN | WHEN NOT MATCHED] ... [UPDATE|INSERT|DELETE] ... ;"
I need to add 1 extra row just after the semicolon
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
So My new file will look like something below
begin
AFFECTED_ROWS := 0;
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
DELETE FROM table_name
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
end;
I tried finding and implementing the approach in the scope of PLSQL but didn't find any generic way possible to get no of rows affected, so I thought
of text parsing but I don't know much about awk or sed.
For now what I was trying to do something like below:
sed '/Patterns Go Here/a AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;' temp.sql
So pattern may have conditions mentioned above
shell-script shell awk grep
shell-script shell awk grep
asked Oct 24 at 22:39
Hargun Suri
6
6
Welcome to Unix & Linux. ;-) You might be better off on our sister site Database Administrators...
– Fabby
Oct 24 at 23:00
add a comment |
Welcome to Unix & Linux. ;-) You might be better off on our sister site Database Administrators...
– Fabby
Oct 24 at 23:00
Welcome to Unix & Linux. ;-) You might be better off on our sister site Database Administrators...
– Fabby
Oct 24 at 23:00
Welcome to Unix & Linux. ;-) You might be better off on our sister site Database Administrators...
– Fabby
Oct 24 at 23:00
add a comment |
1 Answer
1
active
oldest
votes
I have solved it by using perl instead of sed and using the IRS (Input Record Separator - $/) special variable to process lines by semi-colon, rather than by newline.
Any language that supports changing the IRS should work (probably possible with pure bash using IFS=';'
, but I haven't explored this).
In this example, perl will load it's buffer until the input record separator, then process all that content as a line - by changing what that separator is, you can process the file a statement at a time, rather than a line at a time. I can then match the pattern of the statement(s) I'm interested in, and append the affected rows logic to the line before it gets printed.
$ cat test.sql
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
SELECT another-non-matching-statement FROM table;
end;
$ cat test.sql | perl -pe 'BEGIN{$/=";"} m/MERGE INTO .*/ && ($_ .= "nAFFECTED_ROWS := AFFECTED_ROWS + SQL %ROWCOUNT;")'
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
SELECT another-non-matching-statement FROM table;
end;
$
Using less perl shorthand, you might do this:
perl -e '$/=";"; foreach $statement (<>){ print $statement; $statement =~ m/(MERGE INTO .*)|(DELETE FROM)/i && print "nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;" }'
e.g.:
cat test.sql | perl -e '$/=";"; foreach $statement (<>){ print $statement; $statement =~ m/(MERGE INTO .*)|(DELETE FROM)/i && print "nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;" }'
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
SELECT another-non-matching-statement FROM table;
DELETE FROM truncate_me;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
end;
$
perl$/
is the input record separator, not field. awk can do the same (portably) with-vRS=';'
and bash can doread -d';'
but that's nonstandard and less efficient. Note all such approaches fail if any of your statements has a char/string literal containing semicolon likeSET recipe = 'mix this; stir that'
– dave_thompson_085
Oct 25 at 1:30
Good points, thanks dave_thompson. Embedded separators will be many grief, so issues - and handling them will require a lot more sophistication than can be encapsulated in a one-liner. Re field/separator, yeah, I had IFS on the brain from some other work, just typed it without thinking. Thanks for the catch, will edit.
– GarethHumphriesAcc
Oct 25 at 2:28
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f477631%2fhow-can-i-add-some-text-after-some-sequence-of-text-if-this-sequence-matches-cer%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I have solved it by using perl instead of sed and using the IRS (Input Record Separator - $/) special variable to process lines by semi-colon, rather than by newline.
Any language that supports changing the IRS should work (probably possible with pure bash using IFS=';'
, but I haven't explored this).
In this example, perl will load it's buffer until the input record separator, then process all that content as a line - by changing what that separator is, you can process the file a statement at a time, rather than a line at a time. I can then match the pattern of the statement(s) I'm interested in, and append the affected rows logic to the line before it gets printed.
$ cat test.sql
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
SELECT another-non-matching-statement FROM table;
end;
$ cat test.sql | perl -pe 'BEGIN{$/=";"} m/MERGE INTO .*/ && ($_ .= "nAFFECTED_ROWS := AFFECTED_ROWS + SQL %ROWCOUNT;")'
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
SELECT another-non-matching-statement FROM table;
end;
$
Using less perl shorthand, you might do this:
perl -e '$/=";"; foreach $statement (<>){ print $statement; $statement =~ m/(MERGE INTO .*)|(DELETE FROM)/i && print "nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;" }'
e.g.:
cat test.sql | perl -e '$/=";"; foreach $statement (<>){ print $statement; $statement =~ m/(MERGE INTO .*)|(DELETE FROM)/i && print "nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;" }'
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
SELECT another-non-matching-statement FROM table;
DELETE FROM truncate_me;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
end;
$
perl$/
is the input record separator, not field. awk can do the same (portably) with-vRS=';'
and bash can doread -d';'
but that's nonstandard and less efficient. Note all such approaches fail if any of your statements has a char/string literal containing semicolon likeSET recipe = 'mix this; stir that'
– dave_thompson_085
Oct 25 at 1:30
Good points, thanks dave_thompson. Embedded separators will be many grief, so issues - and handling them will require a lot more sophistication than can be encapsulated in a one-liner. Re field/separator, yeah, I had IFS on the brain from some other work, just typed it without thinking. Thanks for the catch, will edit.
– GarethHumphriesAcc
Oct 25 at 2:28
add a comment |
I have solved it by using perl instead of sed and using the IRS (Input Record Separator - $/) special variable to process lines by semi-colon, rather than by newline.
Any language that supports changing the IRS should work (probably possible with pure bash using IFS=';'
, but I haven't explored this).
In this example, perl will load it's buffer until the input record separator, then process all that content as a line - by changing what that separator is, you can process the file a statement at a time, rather than a line at a time. I can then match the pattern of the statement(s) I'm interested in, and append the affected rows logic to the line before it gets printed.
$ cat test.sql
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
SELECT another-non-matching-statement FROM table;
end;
$ cat test.sql | perl -pe 'BEGIN{$/=";"} m/MERGE INTO .*/ && ($_ .= "nAFFECTED_ROWS := AFFECTED_ROWS + SQL %ROWCOUNT;")'
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
SELECT another-non-matching-statement FROM table;
end;
$
Using less perl shorthand, you might do this:
perl -e '$/=";"; foreach $statement (<>){ print $statement; $statement =~ m/(MERGE INTO .*)|(DELETE FROM)/i && print "nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;" }'
e.g.:
cat test.sql | perl -e '$/=";"; foreach $statement (<>){ print $statement; $statement =~ m/(MERGE INTO .*)|(DELETE FROM)/i && print "nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;" }'
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
SELECT another-non-matching-statement FROM table;
DELETE FROM truncate_me;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
end;
$
perl$/
is the input record separator, not field. awk can do the same (portably) with-vRS=';'
and bash can doread -d';'
but that's nonstandard and less efficient. Note all such approaches fail if any of your statements has a char/string literal containing semicolon likeSET recipe = 'mix this; stir that'
– dave_thompson_085
Oct 25 at 1:30
Good points, thanks dave_thompson. Embedded separators will be many grief, so issues - and handling them will require a lot more sophistication than can be encapsulated in a one-liner. Re field/separator, yeah, I had IFS on the brain from some other work, just typed it without thinking. Thanks for the catch, will edit.
– GarethHumphriesAcc
Oct 25 at 2:28
add a comment |
I have solved it by using perl instead of sed and using the IRS (Input Record Separator - $/) special variable to process lines by semi-colon, rather than by newline.
Any language that supports changing the IRS should work (probably possible with pure bash using IFS=';'
, but I haven't explored this).
In this example, perl will load it's buffer until the input record separator, then process all that content as a line - by changing what that separator is, you can process the file a statement at a time, rather than a line at a time. I can then match the pattern of the statement(s) I'm interested in, and append the affected rows logic to the line before it gets printed.
$ cat test.sql
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
SELECT another-non-matching-statement FROM table;
end;
$ cat test.sql | perl -pe 'BEGIN{$/=";"} m/MERGE INTO .*/ && ($_ .= "nAFFECTED_ROWS := AFFECTED_ROWS + SQL %ROWCOUNT;")'
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
SELECT another-non-matching-statement FROM table;
end;
$
Using less perl shorthand, you might do this:
perl -e '$/=";"; foreach $statement (<>){ print $statement; $statement =~ m/(MERGE INTO .*)|(DELETE FROM)/i && print "nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;" }'
e.g.:
cat test.sql | perl -e '$/=";"; foreach $statement (<>){ print $statement; $statement =~ m/(MERGE INTO .*)|(DELETE FROM)/i && print "nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;" }'
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
SELECT another-non-matching-statement FROM table;
DELETE FROM truncate_me;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
end;
$
I have solved it by using perl instead of sed and using the IRS (Input Record Separator - $/) special variable to process lines by semi-colon, rather than by newline.
Any language that supports changing the IRS should work (probably possible with pure bash using IFS=';'
, but I haven't explored this).
In this example, perl will load it's buffer until the input record separator, then process all that content as a line - by changing what that separator is, you can process the file a statement at a time, rather than a line at a time. I can then match the pattern of the statement(s) I'm interested in, and append the affected rows logic to the line before it gets printed.
$ cat test.sql
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
SELECT another-non-matching-statement FROM table;
end;
$ cat test.sql | perl -pe 'BEGIN{$/=";"} m/MERGE INTO .*/ && ($_ .= "nAFFECTED_ROWS := AFFECTED_ROWS + SQL %ROWCOUNT;")'
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
SELECT another-non-matching-statement FROM table;
end;
$
Using less perl shorthand, you might do this:
perl -e '$/=";"; foreach $statement (<>){ print $statement; $statement =~ m/(MERGE INTO .*)|(DELETE FROM)/i && print "nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;" }'
e.g.:
cat test.sql | perl -e '$/=";"; foreach $statement (<>){ print $statement; $statement =~ m/(MERGE INTO .*)|(DELETE FROM)/i && print "nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;" }'
SELECT non-matching-statement FROM table;
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
SELECT another-non-matching-statement FROM table;
DELETE FROM truncate_me;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
end;
$
edited Dec 14 at 3:25
answered Oct 25 at 0:00
GarethHumphriesAcc
812
812
perl$/
is the input record separator, not field. awk can do the same (portably) with-vRS=';'
and bash can doread -d';'
but that's nonstandard and less efficient. Note all such approaches fail if any of your statements has a char/string literal containing semicolon likeSET recipe = 'mix this; stir that'
– dave_thompson_085
Oct 25 at 1:30
Good points, thanks dave_thompson. Embedded separators will be many grief, so issues - and handling them will require a lot more sophistication than can be encapsulated in a one-liner. Re field/separator, yeah, I had IFS on the brain from some other work, just typed it without thinking. Thanks for the catch, will edit.
– GarethHumphriesAcc
Oct 25 at 2:28
add a comment |
perl$/
is the input record separator, not field. awk can do the same (portably) with-vRS=';'
and bash can doread -d';'
but that's nonstandard and less efficient. Note all such approaches fail if any of your statements has a char/string literal containing semicolon likeSET recipe = 'mix this; stir that'
– dave_thompson_085
Oct 25 at 1:30
Good points, thanks dave_thompson. Embedded separators will be many grief, so issues - and handling them will require a lot more sophistication than can be encapsulated in a one-liner. Re field/separator, yeah, I had IFS on the brain from some other work, just typed it without thinking. Thanks for the catch, will edit.
– GarethHumphriesAcc
Oct 25 at 2:28
perl
$/
is the input record separator, not field. awk can do the same (portably) with -vRS=';'
and bash can do read -d';'
but that's nonstandard and less efficient. Note all such approaches fail if any of your statements has a char/string literal containing semicolon like SET recipe = 'mix this; stir that'
– dave_thompson_085
Oct 25 at 1:30
perl
$/
is the input record separator, not field. awk can do the same (portably) with -vRS=';'
and bash can do read -d';'
but that's nonstandard and less efficient. Note all such approaches fail if any of your statements has a char/string literal containing semicolon like SET recipe = 'mix this; stir that'
– dave_thompson_085
Oct 25 at 1:30
Good points, thanks dave_thompson. Embedded separators will be many grief, so issues - and handling them will require a lot more sophistication than can be encapsulated in a one-liner. Re field/separator, yeah, I had IFS on the brain from some other work, just typed it without thinking. Thanks for the catch, will edit.
– GarethHumphriesAcc
Oct 25 at 2:28
Good points, thanks dave_thompson. Embedded separators will be many grief, so issues - and handling them will require a lot more sophistication than can be encapsulated in a one-liner. Re field/separator, yeah, I had IFS on the brain from some other work, just typed it without thinking. Thanks for the catch, will edit.
– GarethHumphriesAcc
Oct 25 at 2:28
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f477631%2fhow-can-i-add-some-text-after-some-sequence-of-text-if-this-sequence-matches-cer%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Welcome to Unix & Linux. ;-) You might be better off on our sister site Database Administrators...
– Fabby
Oct 24 at 23:00