I have the below code
CREATE TABLE Table1(
column1 double NOT NULL,
column2 varchar(60) NULL,
column3 varchar(60) NULL,
column4 double NOT NULL,
CONSTRAINT Index1 PRIMARY KEY CLUSTERED
(
column2 ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY
) ON PRIMARY
GO
GO
and I want to replace
CONSTRAINT Index1 PRIMARY KEY CLUSTERED
(
column2 ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY
) ON PRIMARY
GO
with
)
You can't assume GO is the last character of the file. After Go there can be another table script. How can I do that with single sed or awk.
This may look scary but it is not difficult to grasp with a bit of explanation:
The sed has the following form you may be more familiar with:
sed /regex1/,/regex2/{commands}
First it uses the SOH non-printable as the delimiter
\001
Sets the START and END tags for sed multiline match
Then performs the sed command:
-n
do not print by default$'\x5c'
is a Bash string literal that corresponds to backslash\
The backslashes are necessary to escape the non-printable delimiter on the multiline range match.
{s${SED_DELIM}GO${SED_DELIM})${SED_DELIM};t a;d;:a;};p
:s${SED_DELIM}GO${SED_DELIM})${SED_DELIM}
replace the line that matches GO with)
t a;
if there is a successful substitution in the prior statement then branch to the:a
labeld
if there is no subsitution then delete the linep
print whatever the result is after the commands branch to theI didn't see their answers prior to posting this - this answer is the same as FredPhil/hek2mgl - except in this manner you have a mechanism to be more dynamic on the LHS since you can change the delimiter to a character that is much less likely to appear in the dataset.
With GNU awk for multi-char RS and assuming you want to get rid of the comma before the "CONSTRAINT":
The above works by replacing every stand-alone "GO" with a control char that's unlikely to appear in your input (in this case I used the same value as the default SUBSEP) so we can use that char in a negated character list in the middle gsub() to create a regexp that ends with the first "GO" after "CONSTRAINT". This is one way to do "non-greedy" matching in awk.
If there is no char that you KNOW cannot appear in your input, you can create one like this:
The above initially converts all "a"s to "aA" and "b"s to "aB" so that
and that means that we can now convert all "GO"s to "b"s just like we converted them to "\034" in the first script above. Then we do the main gsub() and then unroll our initial gsub()s.
This idea of
gsub()
ing to create chars that cannot previously exist, using those chars, then unrolling the initialgsub()
s is an extremely useful idiom to learn and remember, e.g. see https://stackoverflow.com/a/13062682/1745001 for another application.To see it working one step at a time:
Update:
You can use the following
sed
command to replace even the last,
before theCONSTRAINT
block:Let me explain it as a multiline script:
You can save the above multiline script in a file and execute it using
You can use the following
sed
command:The pattern searches for a line containing
/CONSTRAINT/
. If the pattern is found a block of commands is started wrapped between{ }
. In the block we first define a labela
through:a
. The we get the next line of input throughN
and append it to the pattern buffer. Unless we find the pattern/GO/!
we'll continue at labela
using the branch commandb
. If the pattern/GO/
is found we simply replace the buffer by a)
.An alternative can be using using a range like FredPhil suggested: