0

I have a file with Server and Domain names in it as below.

Names.txt :

ABCDomain ContractABCServer_1
ABCDomain ABC_server1
LinkDomain CoreLinkServer_1
TADDomain TADServer_1

(I'm getting above file after performing sort and unique operations to some other file.)---just additional info

I need to extract values from above file and pass it to a xyz command (the command is used to restart servers) as a parameter in below format.

O/P:

"ABCDomain(server:ContractABCServer_1,server:ABC_server1)","LinkDomain(server:CoreLinkServer_1)","TADDomain(TADServer_1)"

I m using below stated logic, but it doesn't give me the desired output as the DomainName has to come just once for each set. Also I m having trouble in keeping the same line.

-----------START------

    DOMAIN=''

IFS=' '
while read line
do
        DOMAIN=$(echo "$line" | awk -F " " '{print $1}')

        for word in $line
        do
                if [[ "$word" == "$DOMAIN" ]]; then
                        Server=$(echo "$line" | awk -F " " '{print $2}' )
                        echo -n "(server:$ServerName"
                fi

        done

done < Names.txt
0
{
    if (dom[$1]) 
        dom[$1]=dom[$1]","$2
    else 
        dom[$1]=$2
} 

END {
    ORS=",";
    for (d in dom)
        if (d)
            print ("\""d"(server:"dom[d]")""\"")
}

This is quick and dirty awk solution. Save it like something.awk, then run:

awk -f something.awk Names.txt 

A quick fix in reply to your comment:

{ dom[$1]=dom[$1] ? dom[$1]",server:"$2 : "server:"$2 }

END {
    for (d in dom)
        if (d) {
            out && out = out","
            out = out"\""d"("dom[d]")""\""
        }
        print out
}
  • I used it and it has worked perfectly well. But there is a little change in the required o/p as below. "ABCDomain(server:ContractABCServer_1,server:ABC_server1)" I need "server" string before every server, not just at the beginning. Sorry for the previous typo. Hope it's possible – Aditya Telang Jun 21 '18 at 10:03
  • Can it be done. – Aditya Telang Jun 26 '18 at 12:13
0

You can assemble the comma-separated strings directly in awk and print the composite at the end:

  $1 == "ABCDomain"  {d = (d == "") ? $2 : d "," $2; next} 
  $1 == "LinkDomain" {l = (l == "") ? $2 : l "," $2; next} 
  $1 == "TADDomain"  {t = (t == "") ? $2 : t "," $2; next} 

  END {
    printf("\"ABCDomain(server:%s)\",\"LinkDomain(server:%s)\",\"TADDomain(%s)\"\n", d, l, t)
  }

Ex.

$ awk '
  $1 == "ABCDomain"  {d = (d == "") ? $2 : d "," $2; next} 
  $1 == "LinkDomain" {l = (l == "") ? $2 : l "," $2; next} 
  $1 == "TADDomain"  {t = (t == "") ? $2 : t "," $2; next} 

  END {
    printf("\"ABCDomain(server:%s)\",\"LinkDomain(server:%s)\",\"TADDomain(%s)\"\n", d, l, t)
  }' Names.txt
"ABCDomain(server:ContractABCServer_1,ABC_server1)","LinkDomain(server:CoreLinkServer_1)","TADDomain(TADServer_1)"
0

You can use this code, please read the code before executing it as it is creating a directory in /tmp folder named domains and then removing it the end

 DOMAIN=''

    IFS=' '
    declare -A domain
    mkdir /tmp/domains
    while read line
    do
            DOMAIN=$(echo $line | awk  '{print $1}')
            SERVER=$(echo $line | awk '{print $2}' )
            echo "$SERVER," >> /tmp/domains/$DOMAIN
            domain[$DOMAIN]=1
    done < Names.txt

    sed -ir "$ s/.,$//" /tmp/domains/*

    for i in "${!domain[@]}"; do
             echo -n "$i(server:";
             while read line ; do
                 echo -n "$line" ;
             done < /tmp/domains/$i
             echo ")"
    done
    rm -rf /tmp/domains

This is creating a folder in /tmp folder with the following data, such that each Domain file name has a list of Servers contained in them

$ ls -lhtr /tmp/domains/
total 12K
-rw-rw-r-- 1 arushirai arushirai 11 Jun 19 17:54 TADDomain
-rw-rw-r-- 1 arushirai arushirai 16 Jun 19 17:54 LinkDomain
-rw-rw-r-- 1 arushirai arushirai 32 Jun 19 17:54 ABCDomain

$ cat /tmp/domains/ABCDomain 
ContractABCServer_1,
ABC_server
$ cat /tmp/domains/LinkDomain 
CoreLinkServer_
$ cat /tmp/domains/TADDomain 
TADServer_
0

(Updated to correct the output format)

Using awk:

BEGIN { OFS = "," }

{ servers[$1] = (servers[$1] == "" ? "server:" $2 : servers[$1] "," "server:" $2 ) }

END {
    $0 = ""
    for (domain in servers)
        $(++n) = sprintf("\"%s(%s)\"", domain, servers[domain])

    print
}

This would add the servers as a comma-delimited string to the specific domain in the main block while parsing the input file. This is done by modifying the servers array which holds the servers for a particular domain (the domain is the key in the array).

In the END block, we loop over all keys/domains in the servers array and create an output record in the specified format.

Running this on the supplied data:

$ awk -f script.awk names.txt
"TADDomain(server:TADServer_1)","ABCDomain(server:ContractABCServer_1,server:ABC_server1)","LinkDomain(server:CoreLinkServer_1)"

A mostly equivalent bash script (requires bash 4.3+ for the associative array):

declare -A servers

while read domain server; do
    servers[$domain]+="${servers[$domain]:+,}server:$server"
done <names.txt

for domain in "${!servers[@]}"; do
    out+="${out:+,}\"$domain(${servers[$domain]})\""
done

printf '%s\n' "$out"

... but see "Why is using a shell loop to process text considered bad practice?".

  • Thanks. About the artice "Why is using a shell loop....." I read it, but I m still learning to use text processing basics. – Aditya Telang Jun 27 '18 at 9:03
  • How can we neglect the single quotes that appear while accessing a variable using "$". Is there any other way of calling a variable that doesn't give single quotes. – Aditya Telang Jun 27 '18 at 12:20
  • @AdityaTelang I'm not quite of which single quotes you refer to. – Kusalananda Jun 27 '18 at 12:28
  • Let's say I have a command xyz.sh and I have stored the value of awk -f script.awk names.txt in a variable called PARAM. Now I run the command in script like below:- xyz.sh -domains $PARAM Here the $PARAM is resolving into --> '"TADDomain(server:TADServer_1)"' instead of "TADDomain(server:TADServer_1)" Extra quotes are comming at end and begginning which is corrupting the command. – Aditya Telang Jun 27 '18 at 12:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.