Shell script to merge and delete lines


POLY_STATS   
{     
EqName 103_tri    
Id 123    
act_polyCount 1    
act_polyValue 0    
}     
POLY_STATS
{     
EqName 103_tri    
Id 123    
pass_polyCount 2
pass_polyValue 0    
}     
POLY_STATS
{     
EqName 103    
Id 123    
mes_polyCount 2    
mes_polyValue 0    
}     
POLY_STATS
{   
EqName 504    
Id 123    
mes_polyCount 2    
mes_polyValue 0    
}     
}

My requirement is a shell script to merge the block where the EqName and Id are same and remove the second block.The value of EqName and Id may change. So there should be a dynamic approach to get the value of EqName and Id
The output should be:

POLY_STATS   
{     
EqName 103_tri    
Id 123    
act_polyCount 1    
act_polyValue 0 
pass_polyCount 2
pass_polyValue 0    
}     
 
POLY_STATS
{     
EqName 103    
Id 123    
mes_polyCount 2    
mes_polyValue 0    
}     
POLY_STATS
{   
EqName 504    
Id 123    
mes_polyCount 2    
mes_polyValue 0    
}     
}

The algorithm i am thinking of is:
Get the value of EqName
Get the value of Id
Match for the second occurence of EqName and Id
Get the two lines below the second occurence of Id and move those two lines after the first occurence of Id.
Delete two lines above and 4 lines below the first occurence of EqName

Is the above algorithm seems good .Can anyone pl. help me with any other oneliners or using awk/sed by which we can do this easily

Is this a homework assignment?

What operating system are you using?

What shell are you using?

Why are there two closing braces ( } ) at the end of your input and output files?

Are the blocks you want to merge always located adjacently in you input files, or do they just happen to be that way in your sample input?

What do you mean by "The value of EqName and Id may change. So there should be a dynamic approach to get the value of EqName and Id"? Are you saying the values following those fixed strings may change? (That seems obvious as a means of determining which blocks to merge.) Or, are you saying that the fixed strings EqName and Id may change as well as the values that follow them? Is there some reason that you can't just compare the first pair of lines following a line containing an opening brace without caring what characters are on those pairs of lines?

What have you tried to solve this problem on your own? Where are you stuck?

Hi,
I am using Linux operating system and using bash shell.
The } are part of the input file and cannot be changed as i need them in the output file as well.
The blocks i want to merge is not always located adjacent to each other. They can be positioned at any line number in the file.
Eq Name and Id are fixed strings

I have tried with the following code and i am stuck on how to move the lines and delete the block.

#cat -n file
 1  POLY_STATS
     2  {
     3  EqName 103_tri
     4  Id 123
     5  act_polyCount 1
     6  act_polyValue 0
     7  }
     8  POLY_STATS
     9  {
    10  EqName 103_tri
    11  Id 123
    12  pass_polyCount 2
    13  pass_polyValue 0
    14  }
    15  POLY_STATS
    16  {
    17  EqName 103
    18  Id 123
    19  mes_polyCount 2
    20  mes_polyValue 0
    21  }
    22  POLY_STATS
    23  {
    24  EqName 504
    25  Id 123
    26  mes_polyCount 2
    27  mes_polyValue 0
    28  }
    29  }

 sort file | uniq -c | grep EqName|gawk '$1==2{print $3}' #Get the value of Eqname,which is repeating twice
 cat -n file|sed -n '/103_tri/p' #get line number where EqName is coming twice
 From=$(cat -n file|sed -n '/103_tri/p'|awk '{print $1}'|tail -1)
 echo $From #10
 From=$(echo "$From + 2" | bc)
 To=$(echo "$From + 1" | bc)
 sed -n $From,${To}p file # Printing the lines from the second block which i want to move to the first block

I have printed the lines to be moved

pass_polyCount 2
pass_polyValue 0

Now i want to insert the above two lines after line no 6 and delete the lines from 8 to 14. Pl help

You did not answer Don Cragun's first question. And, if the records belonging to each other are not adjacent, what order should they be printed in?

This looks like a continuation of your earlier thread in September (rather than homework/coursework).
Here is an awk script that does a merge like you want:

#!/bin/sh
awk '
$1=="}" { bl-- }
bl>0 {
  # we are within a { } frame
  if ($1=="EqName") {
    eqname=$0
  } else if ($1=="Id") {
    id=$0
  } else {
    # ORS is a newline
    key=(eqname ORS id)
    if (key in store) {
      # append string
      store[key]=(store[key] ORS $0)
    } else {
      # new string
      store[key]=$0
      # enforce the original order with a number-indexed array
      ind[++cnt]=key
    }
  }
}
$1=="{" { bl++ }
END {
  # walk through the number-indexed array
  # "for (key in store)" would be a random order
  for (c=1; c<=cnt; c++) {
    key=ind[c]
    print "POLY_STATS"
    print "{"
    print key
    print store[key]
    print "}"
  }
}
' file

The { } frame and the text outside are hard-coded in print statements.

1 Like

Thanks a ton !! It helped.