Find a tag with data and replace its data in another tag

Hi I have one file,

:16R::GENL
:20C::RELA//SET//ABC123456
:22F::XYZYESR
:20C::MITI//NETT/QWERTY12345
:16S::GENL

:16R::GENL
:20C::RELA//SET//XYZ23456
:22F::XYZYESR
:16S::GENL

The requirement is, if :20C::MITI// is present in any block, then replace the data of :20C::MITI// in :20C::RELA//

The expected output of the above example is :

:16R::GENL
:20C::RELA//NETT/QWERTY12345
:22F::XYZYESR
:20C::MITI//NETT/QWERTY12345
:16S::GENL

:16R::GENL
:20C::RELA//SET//XYZ23456
:22F::XYZYESR
:16S::GENL

Hello Soumyadip Dutta,

Welcome to forums, I hope you will enjoy learning and sharing knowledge here. Coming to your question, if your actual Input_file is same as sample shown then following may help you in same.

awk '
/:16S::GENL/{
   flag=""
}
/:16R::GENL/{
   flag=1
}
flag && /:20C::RELA/{
   val=$0;
   getline;
   val1=$0;
   getline;
   if($0 ~ /:20C::MITI/){
      sub("SET//ABC123456","NETT/QWERTY12345",val)
};
   print val ORS val1 ORS $0;
   next
};
1
'   Input_file
 

Thanks,
R. Singh

1 Like

Thanks RavinderSingh13!!

It is working.
But there is one requirement.
The values of :20C::MITI/ and :20C::RELA/ are not fixed and may vary from blocks to blocks.

Could you help me in using a variable to fetch the values and then substitute it.

sub("SET//ABC123456","NETT/QWERTY12345",val)

The above part needs to be changed, since they are not fixed.

Thanks again!!
Soumyadip

Hello Soumyadip Dutta,

You could HIT a THANKS button here if you want to thank to a person for a useful post as post's left corner. Coming to your question now, if those values are NOT fixed then could you please do let me know what is the pattern to catch these lines then?

Thanks,
R. Singh

1 Like

Ravinder,

the pattern is as follows:

:20C::RELA//SET//ABC123456
:22F::XYZYESR
:20C::MITI//NETT/QWERTY12345

The red parts are fixed, and we have to identify using them.
The blue parts can change.

So whenever there is a pattern ":20C::MITI//" is occurring after the pattern ":20C::RELA//" within a block, the value of the pattern ":20C::MITI//" which is "NETT/QWERTY12345" has to replaced in the pattern ":20C::RELA//".

Output :

:20C::RELA//NETT/QWERTY12345
:22F::XYZYESR
:20C::MITI//NETT/QWERTY12345

Note that the start and the end of a block is determined by the below patterns:

:16R::GENL -- start
:16S::GENL -- end

Please let me know if you need more details.

Try:

awk '
  {
    for(i=1; i<=NF; i++) {
      if($i~/:20C::RELA/) f=i
      if($i~/:20C::MITI/) {
        s=$i
        sub("[^/]*", x, s)
        sub("//.*", s, $f)
      }
    }
  }
  1
' RS= FS='\n' OFS='\n' ORS='\n\n' file
1 Like

Hey Scrutinizer,

Its working.

:b:

Hello Soumyadip Dutta,

Could you please try following and let me know if this helps you.

awk -F'//' '
/:16S::GENL/{
  flag=""
}
/:16R::GENL/{
  flag=1
}
flag && /:20C::RELA/{
  val1=$1;
  val2=$2;
  getline;
  val3=$0;
  getline;
  if($0 ~ /:20C::MITI/){
    sub(/.*/,$2,val2)
};
  print val1 FS val2 ORS val3 ORS $0;
next
};
1
'    Input_file
 

Kindly do let me know if you have any queries on same.

Thanks,
R. Singh

Is the RELA line ALWAYS preceding the MITI line? Then, try also

awk '
/:20C::RELA/    {T = $0
                 sub ("^" $1, _, T)
                }
/:20C::MITI/    {sub ("/.*", T)
                }
!NF             {T = ""
                }
1
' FS="/" file

If not, try this modification of Scrutinizer's fine proposal:

awk '
        {for(i=1; i<=NF; i++)   {if ($i~/:20C::RELA/) R = i
                                 if ($i~/:20C::MITI/) M = i
                                }
         if (M)                 {$M = $R
                                 sub ("RELA", "MITI", $M)
                                }
         R = M = ""
        }
 1
' RS= FS='\n' OFS='\n' ORS='\n\n' file