Tuesday, November 16, 2021

[SOLVED] Creating just one looping to make list - Shell

Issue

I want to create a .xml file with an specific config, this config needs an hostname and ip, i have created the hosts.csv to input this data being them vm-tmb-test1;127.0.0.1 on .csv file for each separator line ";" is a hostname and ip of a server, but the looping i have created print for each ip in the hosts.csv

Code Structure

#!/bin/bash

for i in $(cat /var/projects/etc/hosts.csv | cut -d\; -f1)
do
    for ips in $(cat /var/projects/etc/hosts.csv | cut -d\; -f2)
    do
        if [[ ${i} == *"jua"* ]]
        then
            sed -i '$ a <node name="'${i}'" tags="infra,jua,vm" hostname="'${ips}'" username="test"/>' /var/projects/etc/resources.xml
        elif [[ ${i} == *"tmb"* ]]
        then
            sed -i '$ a <node name="'${i}'" tags="infra,tmb,vm" hostname="'${ips}'" username="tests"/>' /var/projects/etc/resources.xml 
        fi
    done
done

Host.csv content:

vm-tmb-test1;127.0.0.1
vm-tmb-test2;127.0.0.2
vm-tmb-test3;127.0.0.3
vm-jua-test4;127.0.0.4

Desired Output:

<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.1" username="test"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.2" username="test"/>
<node name="vm-tmb-test3" tags="infra,tmb,vm" hostname="127.0.0.3" username="test"/>
<node name="vm-jua-test4" tags="infra,jua,vm" hostname="127.0.0.4" username="test"/>

Actual Code Output:

<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.1" username="test"/>
<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.2" username="test"/>
<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.3" username="test"/>
<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.4" username="test"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.1" username="test"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.2" username="test"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.3" username="test"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.4" username="test"/>

How can i fix that?

Edit 1: host.csv contains then more of 200 servers hostname and ip's it will be fed with time.


Solution

While faster solutions (eg, awk, sed) exist, for this answer I'm going to stick with OP's idea of using a loop ...

Sample input:

$ cat host.csv
vm-tmb-test1;127.0.0.1
vm-tmb-test2;127.0.0.2
vm-tmb-test3;127.0.0.3
vm-jua-test4;127.0.0.4

Since the sample code appears to just be appending output to a *.xml file I'm going to opt for a single while loop that generates the desired output:

while IFS=";" read -r i ips                             # use ';' as input delimiter and read values into our 2 variables 'i' and 'ips'
do
        tag='UNDEFINED'                                 # define some defaults in case 'i' does not 
        uname='UNDEFINED'                               # have a match in our case statement

        case "${i}" in                                  # pattern match 'i' to determine what strings to submit to the printf command
                *jua*)  tag='jua' ; uname='test'   ;;
                *tmb*)  tag='tmb' ; uname='tests'  ;;
        esac

        printf '<node name="%s" tags="infra,%s,vm" hostname="%s" username="%s"/>\n' "${i}" "${tag}" "${ips}" "${uname}"

done < host.csv

The above generates:

<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.1" username="tests"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.2" username="tests"/>
<node name="vm-tmb-test3" tags="infra,tmb,vm" hostname="127.0.0.3" username="tests"/>
<node name="vm-jua-test4" tags="infra,jua,vm" hostname="127.0.0.4" username="test"/>

NOTES:

  • OP can redirect the output of the printf to the final destination
  • this should be a bit more efficient than repetitive sed -i calls
  • I have copied OPs code snippet that shows the use of username="{test|tests}" (though OP's sample output only shows the string test); OP can edit the proposed code as needed


Answered By - markp-fuso