Using sed to find and replace complex string (preferrably with regex)
sed -i -E "s/(<username>.+)name(.+<\/username>)/\1something\2/" file.xml
This is, I think, what you're looking for.
Explanation:
- parentheses in the first part define groups (strings in fact) that can be reused in the second part
\1
,\2
, etc. in the second part are references to the i-th group captured in the first part (the numbering starts with 1)-E
enables extended regular expressions (needed for+
and grouping).
sed -e '/username/s/CDATA\[name\]/CDATA\[something\]/' \
-e '/password/s/CDATA\[password\]/CDATA\[somethingelse\]/' \
-e '/dbname/s/CDATA\[name\]/CDATA\[somethingdifferent\]/' file.txt
The /username/
before the s
tells sed to only work on lines containing the string 'username'.
If sed
is not a hard requirement, better use a dedicated tool instead.
If your file is valid XML (not just those 3 XML-looking tags), then you can use XMLStarlet:
xml ed -P -O -L \
-u '//username/text()' -v 'something' \
-u '//password/text()' -v 'somethingelse' \
-u '//dbname/text()' -v 'somethingdifferent' file.xml
The above will also work in situations which would be difficult to solve with regular expressions:
- Can replace the values of the tags without specifying their current values.
- Can replace the values even if they are just escaped and not enclosed in CDATA.
- Can replace the values even if the tags have attributes.
- Can easily replace just occurrences of tags, if there are multiple with the same name.
- Can format the modified XML by indenting it.
Brief demonstration of the above:
bash-4.2$ cat file.xml
<sith>
<master>
<username><![CDATA[name]]></username>
</master>
<apprentice>
<username><![CDATA[name]]></username>
<password>password</password>
<dbname foo="bar"><![CDATA[name]]></dbname>
</apprentice>
</sith>
bash-4.2$ xml ed -O -u '//apprentice/username/text()' -v 'something' -u '//password/text()' -v 'somethingelse' -u '//dbname/text()' -v 'somethingdifferent' file.xml
<sith>
<master>
<username><![CDATA[name]]></username>
</master>
<apprentice>
<username><![CDATA[something]]></username>
<password>somethingelse</password>
<dbname foo="bar"><![CDATA[somethingdifferent]]></dbname>
</apprentice>
</sith>