2017-01-20

Using sed to replace parts of specific lines in a file

In this example we are using the following test file test.tmp (here listed, part of it) where we will replace the Oracle DB Version (the 11.2.0.4.0 below) between the path (/u00/app/oracle/product/) and . P0_EE in the line for DB  DB00001 by a new version string "--.-.-.-.-"
#SID;ORACLE_HOME;Position;Type;Standby;Cluster;DB-instances
. . .
DB00001;/u00/app/oracle/product/11.2.0.4.0.P0_EE;60;I;N;S;
DB00002;/u00/app/oracle/product/11.2.0.4.0.P0_EE;70;I;N;S;

This tests are performed under Linux in the bash shell.

In order to be flexible, we are using the following variables:
OS> DB=DB00001
OS> V=--.-.-.-.-

Here the sed command with the regular expression:
OS> sed 's|\('${DB}';/u00/app/oracle/product/\).*\(.P0_EE\)|\1'${V}'\2|g' test.tmp
The output:
#SID;ORACLE_HOME;Position;Type;Standby;Cluster;DB-instances
. . .
DB00001;/u00/app/oracle/product/--.-.-.-.-.P0_EE;60;I;N;S;
DB00002;/u00/app/oracle/product/11.2.0.4.0.P0_EE;70;I;N;S;

Explanation of the regular expression:
The first character after "s" (here the "|") defines the parts separator.
(Slashes (/) are commonly used, but since a big part of our expression is a UNIX path containing slashes, I decided to use another character in order to simplify the interpretation.)
The first part of the expression between the first two "|" (i.e. \('${DB}';/u00/app/oracle/product/\)\(.*\)\(. P0_EE\) ) defines what must match.
The escaped brackets "\(" and "\)" define back references that are referenced by \1 and \3 in the second part of the e.
The value of the variable ${DB} is concatenated with ";/u00/app/oracle/product/ ", forming the first "back reference block" that is referenced by the \1 after the "|".
The expression ".* " matches anything in between blocks one and two. It is not referenced, since if will be replaced by "${V}".
The second "back reference block" (.i.e. "\(.P0_EE\)") matches only ".P0_EE". It is referenced by the \2.

So, in our example, only lines matching the regular expression "DB00001;/u00/app/oracle/product/.*P0_EE" are changed and replaced by the string specified through "\1'${V}'\2" (between the second and third "|").

Another variant - more general and simpler - of the command (ignoring the ".P0_EE" part):
OS> sed 's|\('${DB}';/u00/app/oracle/product/\)\([^;]*\)|\1'${V}'|g' test.tmp

Output:
#SID;ORACLE_HOME;Position;Type;Standby;Cluster;DB-instances
. . .
DB00001;/u00/app/oracle/product/--.-.-.-.-;60;I;N;S;
DB00002;/u00/app/oracle/product/11.2.0.4.0.P0_EE;70;I;N;S;

January 20, 2017 at 10:47AM

No comments :

Post a Comment