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 

    4 Answers 4

    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 } 
    2
    • 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 possibleCommentedJun 21, 2018 at 10:03
    • Can it be done.CommentedJun 26, 2018 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?".

        4
        • Thanks. About the artice "Why is using a shell loop....." I read it, but I m still learning to use text processing basics.CommentedJun 27, 2018 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.CommentedJun 27, 2018 at 12:20
        • @AdityaTelang I'm not quite of which single quotes you refer to.
          – Kusalananda
          CommentedJun 27, 2018 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.CommentedJun 27, 2018 at 12:41

        You must log in to answer this question.

        Start asking to get answers

        Find the answer to your question by asking.

        Ask question

        Explore related questions

        See similar questions with these tags.