-1

I have a file having the below values:

cat data.txt

server1: calv server2: anot log: /u/log/1 server3: calv server4: anot server5: secd server6: calv LIB_TRGT_calv,anot: /tmp/hello.txt LIB_TRGT_secd: /var/del.tmp 

I get the variables starting with LIB_TRGT i.e LIB_TRGT_calv,anot & LIB_TRGT_secd

I need to get the names after TRGT_ from the variable above i.e calv,anot.

considering we got calv & anot; I need to get all the entries having calv & anot and add the entries found in the data.txt as below:

Desired Output:

server1: calv server2: anot log: /u/log/1 server3: calv server4: anot server5: secd server6: calv LIB_TRGT_calv,anot: /tmp/hello.txt LIB_TRGT_secd: /var/del.tmp LIB_server1: /tmp/hello.txt LIB_server2: /tmp/hello.txt LIB_server3: /tmp/hello.txt LIB_server4: /tmp/hello.txt LIB_server6: /tmp/hello.txt LIB_server5: /var/del.tmp 

Likewise for LIB_TRGT_secd

Below is what I did so far:

grep TRGT* data.txt | cut -d: -f1 |cut -d_ -f3 calv,anot secd 

further

grep TRGT* test.txt | cut -d: -f1 |cut -d_ -f3 | sed -n 1'p' | tr ',' '\n' calv anot 

However, secd is missing and i m not sure how to use xargs and further go about it.

Tried the solution by user @Kusalananda but it does not work. See output below:

enter image description here

2
  • Are you sure the first TRGT line is LIB_TRGT_calv,anot: /tmp/hello.txt and not something like LIB_TRGT_calv,LIB_TRGT_anot: /tmp/hello.txt.?CommentedApr 24, 2022 at 18:10
  • i m sure it is LIB_TRGT_calv,anot: /tmp/hello.txt
    – Ashar
    CommentedApr 24, 2022 at 18:10

3 Answers 3

0

An awk program to do this, assuming the LIB_TRGT_ lines always occur after the other lines that these refer to:

BEGIN { FS = ":[[:blank:]]*" OFS = ": " } { print } $1 !~ /^LIB_TRGT_/ { # "list" is an associative array that uses the keys "calv", # "anot", and "secd", and for each of these stores the relevant # servers as a SUBSEP-delimited string. list[$2] = (list[$2] == "" ? $1 : list[$2] SUBSEP $1) next } { path = $2 # Pick out the comma-delimited list of keys after "TRGT_", and # split these up into elements of the array "k". sub("^.*TRGT_", "", $1) nk = split($1, k, ",") $0 = "" $2 = path # For each key, get the corresponding list from "list" and # output the path for each of its values. for (i = 1; i <= nk; ++i) { nv = split(list[k[i]], v, SUBSEP) for (j = 1; j <= nv; ++j) { $1 = "LIB_" v[j] print } } } 

Testing, with the above script in the file script, and with your data in the Unix text file called file:

$ awk -f script file server1: calv server2: anot log: /u/log/1 server3: calv server4: anot server5: secd server6: calv LIB_TRGT_calv,anot: /tmp/hello.txt LIB_server1: /tmp/hello.txt LIB_server3: /tmp/hello.txt LIB_server6: /tmp/hello.txt LIB_server2: /tmp/hello.txt LIB_server4: /tmp/hello.txt LIB_TRGT_secd: /var/del.tmp LIB_server5: /var/del.tmp 

The ordering is slightly different from what you show in the question due to reacting to the LIB_TRGT_ lines as soon as they appear rather than saving them and handling them at the end.

10
  • How do I use this? I saved the awk script in a file called script and then tried this awk -f script data.txt but it does not work. Can you suggest please?
    – Ashar
    CommentedApr 24, 2022 at 18:33
  • @Ashar "It does not work"? Well, then something is wrong. Unfortunately, I can't see what happens when you run that command, and as you can see in my answer, it is clearly working when I copy-and-paste your example data and use that as input. If your data file is a DOS text file (i.e. from a Windows system), you may want to convert it to a Unix text file using the dos2unix tool.
    – Kusalananda
    CommentedApr 24, 2022 at 18:42
  • check my Original post showing your solution's output and let me know if I'm missing something?
    – Ashar
    CommentedApr 24, 2022 at 18:44
  • @Ashar Yeah, your file test.txt is a DOS text file. Please convert it to a Unix text file.
    – Kusalananda
    CommentedApr 24, 2022 at 18:47
  • No, I just created it using vi editor on the server. manually!!
    – Ashar
    CommentedApr 24, 2022 at 18:51
0

We can solve this problem by means of generating code from the data and then applying that generated code to the data itself.

GNU sed with extended regex mode used.

inputf='./data.txt' < "$inputf" \ sed -E ' s/^\s+|\s+$//g s/\s+/\t/g ' | sed -E ' /_TRGT_[^:\t]/{ s/^(([^_]+_)+TRGT_)([^,:]+)[,:](.*(\t\S+))$/\3\5\n\1\4/ h;s/\n.*//;s/.*\t// s:[\/&]:\\&:g;G s/(.*)\n(.*\t).*(\n.*)/\2\1\3/ P } D ' | sed -En ' 1i\ p s#(.*)\t(.*)#/:\\t\1$/{s/^/LIB_/;s/:.*/:\\t\2/;H;ba;}#p $a\ :a\ $!d;g;s/.// ' | sed -Ef - "$inputf" server1: calv server2: anot log: /u/log/1 server3: calv server4: anot server5: secd server6: calv LIB_TRGT_calv,anot: /tmp/hello.txt LIB_TRGT_secd: /var/del.tmp LIB_server1: /tmp/hello.txt LIB_server2: /tmp/hello.txt LIB_server3: /tmp/hello.txt LIB_server4: /tmp/hello.txt LIB_server5: /var/del.tmp LIB_server6: /tmp/hello.txt 

  • Step0, clean the data by removing leading trailing whitespace. Monospace to TABs.
  • Step1 we isolate the key value pairs, put them in one per line.
  • Step2 armed with these kv tuples, we generate sed code.
  • Step3, we apply the code to data.
    0

    The below is a unified solution to both of your scenarios, viz., when the second fields are quoted or not.

    awk -v q=\' '1 NF<2{next} !/^([^_]+_)+TRGT_/ { a[FNR] = $2 b[FNR,$2] = $1 if (index($2,q) == 1) quoted++ next } { n = split($1, temp, /[_,:]/) s=0 for (i=1; i<n; i++) { t = temp[i] s += length(t)+1 ch = substr($1, s-1, 1) if (ch == "_") continue key = (!quoted) ? t : q t q c[key] = $2 } split("", temp, ":") } BEGIN { OFS="\t" } END { for (i=1; i in a; i++) if ( (a[i] in c) && ((i SUBSEP a[i]) in b)) print "LIB_"b[i,a[i]], c[a[i]] }' data.txt server1: 'calv' server2: 'anot' log: '/u/log/1' server3: 'calv' server4: 'anot' server5: 'secd' server6: 'calv' LIB_TRGT_calv,anot: '/tmp/hello.txt' LIB_TRGT_secd: '/var/del.tmp' LIB_server1: '/tmp/hello.txt' LIB_server2: '/tmp/hello.txt' LIB_server3: '/tmp/hello.txt' LIB_server4: '/tmp/hello.txt' LIB_server5: '/var/del.tmp' LIB_server6: '/tmp/hello.txt' 

      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.