Question: Say I have a text file with the following lines:-

```
abcd/efgh/a.jar
{
abcd/efgh/a.class
cdef/ghij/b.class
klmn/opqr/c.class
}
lkmn/opqr/b.zip
{
abcd/efgh/a.class
cdef/ghij/b.class
}
abcd/efgh/a.jar
{
cdef/ghij/b.class
}

```

Now abcd/efgh/a.jar in the first case has abcd/efgh/a.class, cdef/ghij/b.class and klmn/opqr/c.class within the curly braces. Consider it as 1 block of text. Now abcd/efgh/a.jar below again has cdef/ghij/b.class within curly braces. I want to remove this section/block of text. So the final output needs to be like:-

```
abcd/efgh/a.jar
{
abcd/efgh/a.class
cdef/ghij/b.class
klmn/opqr/c.class
}
lkmn/opqr/b.zip
{
abcd/efgh/a.class
cdef/ghij/b.class
}

```

Any help would be highly appreciated :)

Answer: 
After I saw the solution utilizing a `for` loop with `awk` and `sort` and `uniq` and `grep` and `sed` I tried a solution with one tool instead of six:

```
sed ':a
  N;$!ba
  y/\n_/_\n/;s/^/_/
  :b
  s/\(_[^_]*_{\)\([^}]*\)\(_[^_}]*\)\(_[^}]*\)\(_}.*\)\1\([^}]*\)\3_/\1\2\3\4\5\1\6_/;tb
  :c
  s/\(_[^_]*_{\)\([^}]*\)_}\(.*\)\1\([^}]*\)_}/\1\2\4_}\3/;tc
  s/^_//
  y/\n_/_\n/' yourfile

```

does the job, but I have to admit that the regular expressions are easiert to write than to read ... (-;
```
perl -alF'/\n[}{]\n/' -0777ne '
   for ( 0 .. $#F/2 ) {
      my $i = 2*$_;
      my($k,$v) = @F[$i,$i+1];
      if ( exists $h{$k} ) {
         $h{$k} .= join $\, grep { ! exists $seen{$k,$_} } split $\, $v;
      } else {
         push @k, $k;
         $seen{$k,$_}++ for split $\, $h{$k} = $v;
      }
   }
   print "$_\n{\n$h{$_}\n}" for @k;
' yourfile

```

---

Results
-------

```
abcd/efgh/a.jar
{
abcd/efgh/a.class
cdef/ghij/b.class
klmn/opqr/c.class
}
lkmn/opqr/b.zip
{
abcd/efgh/a.class
cdef/ghij/b.class
}

```

---

Working
-------

The input file is slurped and then split up into fields based on the field separator mentioned by the `-F` option. We will be getting even number of elements in the array `@F`. The even numbered then go in as the keys of the hash `%h` whilst their corresp. values are grabbed from the next odd value.

The hash `%h` is populated by splitting up the odd numbered elems on record separator ($\ = \n). At the same time we place the key into the array `@k` so that we can retrieve hash elements in order they were encountered.

All the while only those odd elements are used that are not already seen.