Replace a string before a certain line
Clash Royale CLAN TAG#URR8PPP
up vote
7
down vote
favorite
I have one file like:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 ,
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR ,
PRIMARY INDEX ( CALENDAR_DATE );
I want to replace the ',' by ')' in the line just before the line containing PRIMARY.
The result should be:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
text-processing sed perl
add a comment |Â
up vote
7
down vote
favorite
I have one file like:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 ,
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR ,
PRIMARY INDEX ( CALENDAR_DATE );
I want to replace the ',' by ')' in the line just before the line containing PRIMARY.
The result should be:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
text-processing sed perl
add a comment |Â
up vote
7
down vote
favorite
up vote
7
down vote
favorite
I have one file like:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 ,
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR ,
PRIMARY INDEX ( CALENDAR_DATE );
I want to replace the ',' by ')' in the line just before the line containing PRIMARY.
The result should be:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
text-processing sed perl
I have one file like:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 ,
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR ,
PRIMARY INDEX ( CALENDAR_DATE );
I want to replace the ',' by ')' in the line just before the line containing PRIMARY.
The result should be:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
text-processing sed perl
edited Sep 4 at 15:23


SivaPrasath
1
1
asked Sep 4 at 14:22
Mike
435
435
add a comment |Â
add a comment |Â
5 Answers
5
active
oldest
votes
up vote
10
down vote
accepted
Using GNU sed
:
sed 'N;s/,(s*n.*PRIMARY)/)1/;P;D' file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
N
Read/append the next line of input into the pattern space.P
Print up to the first embedded newline of the current pattern space.D
Delete up to the first embedded newline in the pattern space. Start next cycle, but skip reading from the input if there is still data in the pattern space.
add a comment |Â
up vote
9
down vote
Try reversing the file, doing the string replacement on the line after PRIMARY, then re-reversing the file:
tac file | sed '/PRIMARY/ n; s/,$/)/' | tac
2
+1 for the smartest way.
– SivaPrasath
Sep 4 at 15:14
2
@SivaPrasath - not really, this will fail if the input contains consecutive lines matchingPRIMARY
– don_crissti
Sep 4 at 15:29
@don_crissti ur right!!! at least it works for the OP's input.
– SivaPrasath
Sep 4 at 15:44
add a comment |Â
up vote
8
down vote
try this,
perl -0777 -pe 's/,([^n,]*n[^n]*PRIMARY)/)$1/g'
This will replace the last ,
with )
in lines before any line including PRIMARY
.
Explanation
perl -0777
slurp whole file (read as one line)s/search_pattern/replacement/g
Substitute search pattern with replacement globally
1
Note that.
meta char won't cross line boundaries, unless the/s
modifier is in effect. Hence, you can change the regex tos/,(?=[^,]*n.*PRIMARY)/)/g
– Rakesh Sharma
Sep 4 at 17:44
1
? I don't use.
in my regex.
– RoVo
Sep 5 at 8:32
add a comment |Â
up vote
4
down vote
If you use ed
rather than sed
you can use a regex address with negative offset:
g/PRIMARY/-1 s/,$/)/
Ex.
$ printf 'g/PRIMARY/-1 s/,$/)/n,pnqn' | ed -s file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
or (for in-place editing)
printf 'g/PRIMARY/-1 s/,$/)/nwqn' | ed -s file
The replacement will match ALL instances of /PRIMARY/
- if you only want to replace the first, remove the g
modifier.
+1 for use of The Standard Text Editor
– mirabilos
Sep 4 at 16:54
add a comment |Â
up vote
1
down vote
With POSIX-ly sed
you can do the following:
sed -e '
/PRIMARY/!x;1!p;d;
x;s/,/)/;$G
' input-file.txt
Output:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
Working:
- For non-PRIMARY lines, we save the line and print the one we saved in the hold.
- And for the PRIMARY, we retrieve the previous and effect the transformation.
add a comment |Â
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
10
down vote
accepted
Using GNU sed
:
sed 'N;s/,(s*n.*PRIMARY)/)1/;P;D' file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
N
Read/append the next line of input into the pattern space.P
Print up to the first embedded newline of the current pattern space.D
Delete up to the first embedded newline in the pattern space. Start next cycle, but skip reading from the input if there is still data in the pattern space.
add a comment |Â
up vote
10
down vote
accepted
Using GNU sed
:
sed 'N;s/,(s*n.*PRIMARY)/)1/;P;D' file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
N
Read/append the next line of input into the pattern space.P
Print up to the first embedded newline of the current pattern space.D
Delete up to the first embedded newline in the pattern space. Start next cycle, but skip reading from the input if there is still data in the pattern space.
add a comment |Â
up vote
10
down vote
accepted
up vote
10
down vote
accepted
Using GNU sed
:
sed 'N;s/,(s*n.*PRIMARY)/)1/;P;D' file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
N
Read/append the next line of input into the pattern space.P
Print up to the first embedded newline of the current pattern space.D
Delete up to the first embedded newline in the pattern space. Start next cycle, but skip reading from the input if there is still data in the pattern space.
Using GNU sed
:
sed 'N;s/,(s*n.*PRIMARY)/)1/;P;D' file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
N
Read/append the next line of input into the pattern space.P
Print up to the first embedded newline of the current pattern space.D
Delete up to the first embedded newline in the pattern space. Start next cycle, but skip reading from the input if there is still data in the pattern space.
edited Sep 4 at 15:45
don_crissti
46.9k15124154
46.9k15124154
answered Sep 4 at 14:56


SivaPrasath
1
1
add a comment |Â
add a comment |Â
up vote
9
down vote
Try reversing the file, doing the string replacement on the line after PRIMARY, then re-reversing the file:
tac file | sed '/PRIMARY/ n; s/,$/)/' | tac
2
+1 for the smartest way.
– SivaPrasath
Sep 4 at 15:14
2
@SivaPrasath - not really, this will fail if the input contains consecutive lines matchingPRIMARY
– don_crissti
Sep 4 at 15:29
@don_crissti ur right!!! at least it works for the OP's input.
– SivaPrasath
Sep 4 at 15:44
add a comment |Â
up vote
9
down vote
Try reversing the file, doing the string replacement on the line after PRIMARY, then re-reversing the file:
tac file | sed '/PRIMARY/ n; s/,$/)/' | tac
2
+1 for the smartest way.
– SivaPrasath
Sep 4 at 15:14
2
@SivaPrasath - not really, this will fail if the input contains consecutive lines matchingPRIMARY
– don_crissti
Sep 4 at 15:29
@don_crissti ur right!!! at least it works for the OP's input.
– SivaPrasath
Sep 4 at 15:44
add a comment |Â
up vote
9
down vote
up vote
9
down vote
Try reversing the file, doing the string replacement on the line after PRIMARY, then re-reversing the file:
tac file | sed '/PRIMARY/ n; s/,$/)/' | tac
Try reversing the file, doing the string replacement on the line after PRIMARY, then re-reversing the file:
tac file | sed '/PRIMARY/ n; s/,$/)/' | tac
answered Sep 4 at 14:49
glenn jackman
47.1k265103
47.1k265103
2
+1 for the smartest way.
– SivaPrasath
Sep 4 at 15:14
2
@SivaPrasath - not really, this will fail if the input contains consecutive lines matchingPRIMARY
– don_crissti
Sep 4 at 15:29
@don_crissti ur right!!! at least it works for the OP's input.
– SivaPrasath
Sep 4 at 15:44
add a comment |Â
2
+1 for the smartest way.
– SivaPrasath
Sep 4 at 15:14
2
@SivaPrasath - not really, this will fail if the input contains consecutive lines matchingPRIMARY
– don_crissti
Sep 4 at 15:29
@don_crissti ur right!!! at least it works for the OP's input.
– SivaPrasath
Sep 4 at 15:44
2
2
+1 for the smartest way.
– SivaPrasath
Sep 4 at 15:14
+1 for the smartest way.
– SivaPrasath
Sep 4 at 15:14
2
2
@SivaPrasath - not really, this will fail if the input contains consecutive lines matching
PRIMARY
– don_crissti
Sep 4 at 15:29
@SivaPrasath - not really, this will fail if the input contains consecutive lines matching
PRIMARY
– don_crissti
Sep 4 at 15:29
@don_crissti ur right!!! at least it works for the OP's input.
– SivaPrasath
Sep 4 at 15:44
@don_crissti ur right!!! at least it works for the OP's input.
– SivaPrasath
Sep 4 at 15:44
add a comment |Â
up vote
8
down vote
try this,
perl -0777 -pe 's/,([^n,]*n[^n]*PRIMARY)/)$1/g'
This will replace the last ,
with )
in lines before any line including PRIMARY
.
Explanation
perl -0777
slurp whole file (read as one line)s/search_pattern/replacement/g
Substitute search pattern with replacement globally
1
Note that.
meta char won't cross line boundaries, unless the/s
modifier is in effect. Hence, you can change the regex tos/,(?=[^,]*n.*PRIMARY)/)/g
– Rakesh Sharma
Sep 4 at 17:44
1
? I don't use.
in my regex.
– RoVo
Sep 5 at 8:32
add a comment |Â
up vote
8
down vote
try this,
perl -0777 -pe 's/,([^n,]*n[^n]*PRIMARY)/)$1/g'
This will replace the last ,
with )
in lines before any line including PRIMARY
.
Explanation
perl -0777
slurp whole file (read as one line)s/search_pattern/replacement/g
Substitute search pattern with replacement globally
1
Note that.
meta char won't cross line boundaries, unless the/s
modifier is in effect. Hence, you can change the regex tos/,(?=[^,]*n.*PRIMARY)/)/g
– Rakesh Sharma
Sep 4 at 17:44
1
? I don't use.
in my regex.
– RoVo
Sep 5 at 8:32
add a comment |Â
up vote
8
down vote
up vote
8
down vote
try this,
perl -0777 -pe 's/,([^n,]*n[^n]*PRIMARY)/)$1/g'
This will replace the last ,
with )
in lines before any line including PRIMARY
.
Explanation
perl -0777
slurp whole file (read as one line)s/search_pattern/replacement/g
Substitute search pattern with replacement globally
try this,
perl -0777 -pe 's/,([^n,]*n[^n]*PRIMARY)/)$1/g'
This will replace the last ,
with )
in lines before any line including PRIMARY
.
Explanation
perl -0777
slurp whole file (read as one line)s/search_pattern/replacement/g
Substitute search pattern with replacement globally
edited Sep 4 at 15:01
answered Sep 4 at 14:32
RoVo
1,296211
1,296211
1
Note that.
meta char won't cross line boundaries, unless the/s
modifier is in effect. Hence, you can change the regex tos/,(?=[^,]*n.*PRIMARY)/)/g
– Rakesh Sharma
Sep 4 at 17:44
1
? I don't use.
in my regex.
– RoVo
Sep 5 at 8:32
add a comment |Â
1
Note that.
meta char won't cross line boundaries, unless the/s
modifier is in effect. Hence, you can change the regex tos/,(?=[^,]*n.*PRIMARY)/)/g
– Rakesh Sharma
Sep 4 at 17:44
1
? I don't use.
in my regex.
– RoVo
Sep 5 at 8:32
1
1
Note that
.
meta char won't cross line boundaries, unless the /s
modifier is in effect. Hence, you can change the regex to s/,(?=[^,]*n.*PRIMARY)/)/g
– Rakesh Sharma
Sep 4 at 17:44
Note that
.
meta char won't cross line boundaries, unless the /s
modifier is in effect. Hence, you can change the regex to s/,(?=[^,]*n.*PRIMARY)/)/g
– Rakesh Sharma
Sep 4 at 17:44
1
1
? I don't use
.
in my regex.– RoVo
Sep 5 at 8:32
? I don't use
.
in my regex.– RoVo
Sep 5 at 8:32
add a comment |Â
up vote
4
down vote
If you use ed
rather than sed
you can use a regex address with negative offset:
g/PRIMARY/-1 s/,$/)/
Ex.
$ printf 'g/PRIMARY/-1 s/,$/)/n,pnqn' | ed -s file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
or (for in-place editing)
printf 'g/PRIMARY/-1 s/,$/)/nwqn' | ed -s file
The replacement will match ALL instances of /PRIMARY/
- if you only want to replace the first, remove the g
modifier.
+1 for use of The Standard Text Editor
– mirabilos
Sep 4 at 16:54
add a comment |Â
up vote
4
down vote
If you use ed
rather than sed
you can use a regex address with negative offset:
g/PRIMARY/-1 s/,$/)/
Ex.
$ printf 'g/PRIMARY/-1 s/,$/)/n,pnqn' | ed -s file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
or (for in-place editing)
printf 'g/PRIMARY/-1 s/,$/)/nwqn' | ed -s file
The replacement will match ALL instances of /PRIMARY/
- if you only want to replace the first, remove the g
modifier.
+1 for use of The Standard Text Editor
– mirabilos
Sep 4 at 16:54
add a comment |Â
up vote
4
down vote
up vote
4
down vote
If you use ed
rather than sed
you can use a regex address with negative offset:
g/PRIMARY/-1 s/,$/)/
Ex.
$ printf 'g/PRIMARY/-1 s/,$/)/n,pnqn' | ed -s file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
or (for in-place editing)
printf 'g/PRIMARY/-1 s/,$/)/nwqn' | ed -s file
The replacement will match ALL instances of /PRIMARY/
- if you only want to replace the first, remove the g
modifier.
If you use ed
rather than sed
you can use a regex address with negative offset:
g/PRIMARY/-1 s/,$/)/
Ex.
$ printf 'g/PRIMARY/-1 s/,$/)/n,pnqn' | ed -s file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
or (for in-place editing)
printf 'g/PRIMARY/-1 s/,$/)/nwqn' | ed -s file
The replacement will match ALL instances of /PRIMARY/
- if you only want to replace the first, remove the g
modifier.
edited Sep 4 at 15:58
answered Sep 4 at 15:36
steeldriver
32.1k34979
32.1k34979
+1 for use of The Standard Text Editor
– mirabilos
Sep 4 at 16:54
add a comment |Â
+1 for use of The Standard Text Editor
– mirabilos
Sep 4 at 16:54
+1 for use of The Standard Text Editor
– mirabilos
Sep 4 at 16:54
+1 for use of The Standard Text Editor
– mirabilos
Sep 4 at 16:54
add a comment |Â
up vote
1
down vote
With POSIX-ly sed
you can do the following:
sed -e '
/PRIMARY/!x;1!p;d;
x;s/,/)/;$G
' input-file.txt
Output:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
Working:
- For non-PRIMARY lines, we save the line and print the one we saved in the hold.
- And for the PRIMARY, we retrieve the previous and effect the transformation.
add a comment |Â
up vote
1
down vote
With POSIX-ly sed
you can do the following:
sed -e '
/PRIMARY/!x;1!p;d;
x;s/,/)/;$G
' input-file.txt
Output:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
Working:
- For non-PRIMARY lines, we save the line and print the one we saved in the hold.
- And for the PRIMARY, we retrieve the previous and effect the transformation.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
With POSIX-ly sed
you can do the following:
sed -e '
/PRIMARY/!x;1!p;d;
x;s/,/)/;$G
' input-file.txt
Output:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
Working:
- For non-PRIMARY lines, we save the line and print the one we saved in the hold.
- And for the PRIMARY, we retrieve the previous and effect the transformation.
With POSIX-ly sed
you can do the following:
sed -e '
/PRIMARY/!x;1!p;d;
x;s/,/)/;$G
' input-file.txt
Output:
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0 COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
Working:
- For non-PRIMARY lines, we save the line and print the one we saved in the hold.
- And for the PRIMARY, we retrieve the previous and effect the transformation.
answered Sep 5 at 8:02
Rakesh Sharma
51013
51013
add a comment |Â
add a comment |Â
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
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f466798%2freplace-a-string-before-a-certain-line%23new-answer', 'question_page');
);
Post as a guest
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
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
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