0

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?

7 Answers 7

2

You are not too far:

sed -i "/<dhcp>/a \ \ \ \ \ \ ${string}" "${file_path}"
  • -i to change input file
  • /<dhcp>/ to select only dhcp open tag
  • (\ ) * 6 to indent string content

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>
Sign up to request clarification or add additional context in comments.

Comments

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>

Comments

2

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>
  • N Append the next line to the pattern space
  • s substitute
  • ## The last matched pattern (I have changed the delimiter of the substitute to #)
  • &\n\1 Replace 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>

Comments

1

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

Comments

1

Using bash and sed's a (append) command:

sed '/^[[:blank:]]*<dhcp>[[:blank:]]*$/a'$'\\\n'"$string" "$file_path"

1 Comment

@Thefourthbird Those leading whitespaces are not significant in an xml document. They are for human readability.
0
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>

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.