It's not so much the regex pattern as it is how to achieve it. I've attempted perl, sed, and awk (various attempts with each), but I'm not sure how possible this is as a one-liner (I'd prefer to not write a perl script).
Say I have
#MARKER_TOP
INSERT INTO ('col1', 'col2', 'col3')
VALUES
(123,123,'2018-20-20 24:24:24',123)
...etc.
(123,123,'2018-20-20 24:24:24',123);
#MARKER_BOTTOM
...and more! (not all INSERT tables will be marked, btw)
What I'd like to do is replace all those string dates with SQLs NOW()
. Specifically, with Perl, I've tried the following:
perl -w -pi.bak -e "undef $/; s/(#MARKER_TOP.*)'[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]'(.*#MARKER_BOTTOM)/$1 NOW() $2/msg" test.sql
But it's ripping all of the blocks of interest ( #MARKER_TOP
, etc.) out completely and replacing it with NOW()
which is way too heavy-handed for what I'm wanting.
A simple way is to use the range operator
use warnings;
use strict;
my $file = 'test.sql';
open my $fh, '<', $file or die "Can't open $file: $!";
my $re_date = qr/'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'/;
while (<$fh>)
{
if (/#MARKER_TOP/ .. /#MARKER_BOTTOM/) {
s/$re_date/NOW()/;
}
print;
}
or in a one-liner
perl -wpe"s/'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'/NOW()/
if /#MARKER_TOP/ .. /#MARKER_BOTTOM/
" test.sql
where I delimit the code with "..."
so to be able to use '
inside (there are other ways).
I assume that there is a single date on a line, in the format strictly as given in the question, inside ''
. I tested by adding another INSERT
section but without markers. The replacements happen only in the markers-bracketed one.
The range operator works by keeping the state: once its left operand turns true it becomes true, and it stays true until the right operand turns true, after which it returns false in the next iteration. It works this way in scalar context, while in list context it returns a list within that range. See linked docs.
You can use awk
like this:
awk '/#MARKER_TOP/{m=1} /#MARKER_BOTTOM/{m=0} m{
gsub(/\047[0-9]{4}(-[0-9]{2}){2} [0-9]{2}(:[0-9]{2}){2}\047/, "NOW()")} 1' file
#MARKER_TOP
INSERT INTO ('col1', 'col2', 'col3')
VALUES
(123,123,NOW(),123)
...etc.
(123,123,NOW(),123);
#MARKER_BOTTOM
Here is how it works:
/#MARKER_TOP/{m=1}
: set a flag m=1
when we get text #MARKER_TOP
/#MARKER_BOTTOM/{m=0}
: reset flag m=0
when we get text #MARKER_BOTTOM
m{gsub(/.../, "NOW()")}
: when m==1
then replace date string with NOW()
using regex 1
: print each record
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.