'How to insert text after a certain string in a file with variables
I have these variables:
file_path="/home/dir/file.xml"
string="<host mac='0A:00:DD:D2:00:02' name='vfp-20vr' ip='10.10.1.122'/>"
This is the content of file.xml
<network>
<name>br-ext</name>
<forward mode='route'/>
<bridge name='br-ext' stp='on' delay='0'/>
<mac address='52:54:00:9f:a0:00'/>
<ip address='10.10.1.11' netmask='255.255.255.0'>
<dhcp>
<host mac='0A:AA:FF:C1:A1:EE' name='vsrxa-1' ip='10.10.1.21'/>
<host mac='0A:AA:FF:C1:A2:EE' name='vsrxa-2' ip='10.10.1.22'/>
<host mac='0A:AA:FF:C1:B1:EE' name='vsrxb-1' ip='10.10.1.23'/>
<host mac='0A:AA:FF:C1:B2:EE' name='vsrxb-2' ip='10.10.1.24'/>
<host mac='0A:AA:FF:C1:C1:EE' name='vsrxc-1' ip='10.10.1.25'/>
<host mac='0A:AA:FF:C1:C2:EE' name='vsrxc-2' ip='10.10.1.26'/>
<host mac='0A:AA:FF:C1:D1:EE' name='vsrxd-1' ip='10.10.1.27'/>
<host mac='0A:AA:FF:C1:D2:EE' name='vsrxd-2' ip='10.10.1.28'/>
</dhcp>
</ip>
</network>
I would like to add the $string right after the <dhcp> flag, something like this:
...
<dhcp>
<host mac='0A:00:DD:D2:00:02' name='vfp-20vr' ip='10.10.1.122'/>
<host mac='0A:AA:FF:C1:A1:EE' name='vsrxa-1' ip='10.10.1.21'/>
...
I tried using sed "/\dhcp\/a $string $file_path" in my bash script with no success...
Does anyone know how I can achieve this?
Solution 1:[1]
You are not too far:
sed -i "/<dhcp>/a \ \ \ \ \ \ ${string}" "${file_path}"
-ito change input file/<dhcp>/to select onlydhcpopen tag- (
\) * 6 to indentstringcontent
Result:
<network>
<name>br-ext</name>
<forward mode='route'/>
<bridge name='br-ext' stp='on' delay='0'/>
<mac address='52:54:00:9f:a0:00'/>
<ip address='10.10.1.11' netmask='255.255.255.0'>
<dhcp>
<host mac='0A:00:DD:D2:00:02' name='vfp-20vr' ip='10.10.1.122'/>
<host mac='0A:AA:FF:C1:A1:EE' name='vsrxa-1' ip='10.10.1.21'/>
<host mac='0A:AA:FF:C1:A2:EE' name='vsrxa-2' ip='10.10.1.22'/>
<host mac='0A:AA:FF:C1:B1:EE' name='vsrxb-1' ip='10.10.1.23'/>
<host mac='0A:AA:FF:C1:B2:EE' name='vsrxb-2' ip='10.10.1.24'/>
<host mac='0A:AA:FF:C1:C1:EE' name='vsrxc-1' ip='10.10.1.25'/>
<host mac='0A:AA:FF:C1:C2:EE' name='vsrxc-2' ip='10.10.1.26'/>
<host mac='0A:AA:FF:C1:D1:EE' name='vsrxd-1' ip='10.10.1.27'/>
<host mac='0A:AA:FF:C1:D2:EE' name='vsrxd-2' ip='10.10.1.28'/>
</dhcp>
</ip>
</network>
Solution 2:[2]
Using sed
$ sed "/<dhcp>/{p;s|\( \+\).*|\1 $string|;}" file
<network>
<name>br-ext</name>
<forward mode='route'/>
<bridge name='br-ext' stp='on' delay='0'/>
<mac address='52:54:00:9f:a0:00'/>
<ip address='10.10.1.11' netmask='255.255.255.0'>
<dhcp>
<host mac='0A:00:DD:D2:00:02' name='vfp-20vr' ip='10.10.1.122'/>
<host mac='0A:AA:FF:C1:A1:EE' name='vsrxa-1' ip='10.10.1.21'/>
<host mac='0A:AA:FF:C1:A2:EE' name='vsrxa-2' ip='10.10.1.22'/>
<host mac='0A:AA:FF:C1:B1:EE' name='vsrxb-1' ip='10.10.1.23'/>
<host mac='0A:AA:FF:C1:B2:EE' name='vsrxb-2' ip='10.10.1.24'/>
<host mac='0A:AA:FF:C1:C1:EE' name='vsrxc-1' ip='10.10.1.25'/>
<host mac='0A:AA:FF:C1:C2:EE' name='vsrxc-2' ip='10.10.1.26'/>
<host mac='0A:AA:FF:C1:D1:EE' name='vsrxd-1' ip='10.10.1.27'/>
<host mac='0A:AA:FF:C1:D2:EE' name='vsrxd-2' ip='10.10.1.28'/>
</dhcp>
</ip>
</network>
Solution 3:[3]
You could use a pattern to match the <dhcp> part and capture the leading spaces.
Then append the next string, substitute with the full match for the last pattern followed by a newline and the backreference to keep the same indenting.
From that point on, you can extend it with your own indenting.
sed "/^\([[:space:]]*\)<dhcp>/{N;s##&\n\1 $string#}" "$file_path"
Explanation
/^\([[:space:]]*\)<dhcp>/Natch start of string, capture optional spaces and match<dhcp>NAppend the next line to the pattern spacessubstitute##The last matched pattern (I have changed the delimiter of the substitute to#)&\n\1Replace with the full match, newline and a backreference to group 1 containing the indenting and add your own indenting
Output
<network>
<name>br-ext</name>
<forward mode='route'/>
<bridge name='br-ext' stp='on' delay='0'/>
<mac address='52:54:00:9f:a0:00'/>
<ip address='10.10.1.11' netmask='255.255.255.0'>
<dhcp>
<host mac='0A:00:DD:D2:00:02' name='vfp-20vr' ip='10.10.1.122'/>
<host mac='0A:AA:FF:C1:A1:EE' name='vsrxa-1' ip='10.10.1.21'/>
<host mac='0A:AA:FF:C1:A2:EE' name='vsrxa-2' ip='10.10.1.22'/>
<host mac='0A:AA:FF:C1:B1:EE' name='vsrxb-1' ip='10.10.1.23'/>
<host mac='0A:AA:FF:C1:B2:EE' name='vsrxb-2' ip='10.10.1.24'/>
<host mac='0A:AA:FF:C1:C1:EE' name='vsrxc-1' ip='10.10.1.25'/>
<host mac='0A:AA:FF:C1:C2:EE' name='vsrxc-2' ip='10.10.1.26'/>
<host mac='0A:AA:FF:C1:D1:EE' name='vsrxd-1' ip='10.10.1.27'/>
<host mac='0A:AA:FF:C1:D2:EE' name='vsrxd-2' ip='10.10.1.28'/>
</dhcp>
</ip>
</network>
Solution 4:[4]
try this
#! /bin/bash
file_path="$HOME/test.xml"
content="<host>b</host>"
c=$(echo $content | sed 's/\//\\\//g')
sed "/<\/dhcp>/ s/.*/${c}\n&/" $file_path
Solution 5:[5]
Using bash and sed's a (append) command:
sed '/^[[:blank:]]*<dhcp>[[:blank:]]*$/a'$'\\\n'"$string" "$file_path"
Solution 6:[6]
strings=" STRING1...\n STRING2...\n ...\n"
match="<dhcp>"
awk -v m="$match" -v s="$strings" '{ print; if($1 == m) printf s }' input_file
<network>
<name>br-ext</name>
<forward mode='route'/>
<bridge name='br-ext' stp='on' delay='0'/>
<mac address='52:54:00:9f:a0:00'/>
<ip address='10.10.1.11' netmask='255.255.255.0'>
<dhcp>
STRING1...
STRING2...
...
<host mac='0A:AA:FF:C1:A1:EE' name='vsrxa-1' ip='10.10.1.21'/>
<host mac='0A:AA:FF:C1:A2:EE' name='vsrxa-2' ip='10.10.1.22'/>
<host mac='0A:AA:FF:C1:B1:EE' name='vsrxb-1' ip='10.10.1.23'/>
<host mac='0A:AA:FF:C1:B2:EE' name='vsrxb-2' ip='10.10.1.24'/>
<host mac='0A:AA:FF:C1:C1:EE' name='vsrxc-1' ip='10.10.1.25'/>
<host mac='0A:AA:FF:C1:C2:EE' name='vsrxc-2' ip='10.10.1.26'/>
<host mac='0A:AA:FF:C1:D1:EE' name='vsrxd-1' ip='10.10.1.27'/>
<host mac='0A:AA:FF:C1:D2:EE' name='vsrxd-2' ip='10.10.1.28'/>
</dhcp>
</ip>
</network>
Solution 7:[7]
For a similar task I use xmlstarlet. Obviously you got $string from a xml source. Thus you can use xmlstarlet to get mac, name and ip values. Let's assume you got them. You can then add a new host into $file_path like this:
xmlstarlet edit --inplace \
--insert /network/ip/dhcp/host[1] --type elem --name new_host --value "" \
--insert //new_host --type attr --name mac --value $new_host_mac \
--insert //new_host --type attr --name name --value $new_host_name \
--insert //new_host --type attr --name ip --value $new_host_ip \
--rename //new_host --value host \
$file_path
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Arnaud Valmary |
| Solution 2 | HatLess |
| Solution 3 | |
| Solution 4 | Splinter1984 |
| Solution 5 | M. Nejat Aydin |
| Solution 6 | |
| Solution 7 | seeker |
