Add delimiter to a file from layout file

I need to add delimiter in file abc.txt using layout.txt
for eg 1 to 2 is category field so after that I need to add delimiter ~

abc.txt

110101160315100000000000000
 110101160315100000000000000

Layout.txt

CATEGORY                      POSITION  (1:2)       char,     2
GROUP_ID                      POSITION  (3:4)       char,     2
 DOR_MONTH                   POSITION  (9:10)      char,     2

abc.txt with delimiter

11~01~01160~315100000000000000
 11~01~01160~315100000000000000

the way I am trying is
1)Read the file Layout.txt line by line
2)Get position of ( , ) ,:
3)set the position of start and end position
4)read abc.txt and append the file with ~ at above given location.

However I got stuck in step 3 which is as below , variable in index gives error.
also Is there any better and efficient method to do it ?

 
  
 #!/usr/bin/ksh 
 input="./Emi11LayoutAsDefinedInCLEC.TXT"
start_character="("
end_character=")"
tmp=":"
 function getPosition
{   
   echo "getPosition : $var"
   S=`echo $var |awk '{print index($0,$start_character)}'`
   E=`echo $var |awk '{print index($0,$end_character)}'`
   echo "START POSITION of $start_position --------------------->: " $S
   echo "END POSITION of $end_position --------------------->: " $E    
   
}
 count=0
while IFS= read -r var
do
   echo "Reading : Starts **********"
   echo $var
   getPosition $var   
   echo "Reading : Finish **********"
   ((count=$count+1))
done < "$input"
 

what about field(s) from position 4 to 9 . Could you please provide your input file

I am assuming layout.txt will have all the fields in ascending order with no. of characters seperated by ","(comma).
Please try below code.

awk -F"," 'NR==FNR{a[NR]=$2;ln=NR;next;}
{ s=1
for(i=1;i<=ln;i++) {
str1=substr($0,s,a)
s=s+a
printf i==ln ? str1"\n":str1"~"
}
 }' layout.txt abc.txt

It's not quite clear what you want, do you want a delimiter

  • before the respective field (but not for the first field)
  • after the respective field (but not for the last field)
  • both but removing double delimiters
    ?

Please be aware that the sample output is not consistent - the delimiter is in the middle of DOR_MONTH.

Ok let me put it again
Sample file
abc.txt
-------------

110101160315100000000000000
110101160315100000000000000

Layout.txt
--------------

CATEGORY                      POSITION  (1:2)       char,     2
GROUP_ID                      POSITION  (3:4)       char,     2
DOR_MONTH                     POSITION  (9:10)      char,     2

About layout means position
-from 1 to 2 is Category and hence we need separator
-from 3 to 4 is GROUP_ID and hence we need separator
-from 9 to 10 is DOR_MONTH and hence we need separator
Final output
--------------

11~01~0116~03~15100000000000000
11~01~0116~03~15100000000000000

using perl

my $sourceFile="/v/global/user/b/bh/bharade/Programs/Forum_Scripts/Layout.txt";
my $targetFile="/v/global/user/b/bh/bharade/Programs/Forum_Scripts/abc.txt";

open(FH1,"$sourceFile") or die "$!\n";
open(FH2,"$targetFile") or die "$!\n";
my $i=1;
while  (<FH1>) {
  if (/(\d+)\:(\d+)/) {
    my $start=$1;
    my $end=$2;
    if ($. == 1) {
      if ( $start != 1) {
        my $newEnd=$start - 1;
        my $newStart=0;
        $hash{$i}=[$newStart,$newEnd];
        ++$i;
      }
    }
    $hash{$i}=[$start - 1,$end];
    ++$i;
  }
}
my $prevEnd=0;
while (<FH2>) {
  foreach ($j=1;$j<$i;$j++){
    if ( ($hash{$j}->[0] - $prevEnd ) > 1 ) {
      $gapstart=$hash{$j}->[0] - $prevEnd;
      $gapEnd=$hash{$j}->[0] - 1;
      print substr ($_,$gapstart,$gapstart),"~";
    }

    print substr ($_,$hash{$j}->[0],$hash{$j}->[1] - $hash{$j}->[0] ),"~";
    $prevEnd = $hash{$j}->[1];
  }
  if (length($_) != $prevEnd ) {
    print substr ($_,$prevEnd);
  }
}

close (FH1);
close (FH2);

Is it possible to do in only unix Korn shell file???

Try this pure shell ( bash ):

while IFS=" 	(:)" read _ _ P _ _ L; do ((IX++)); POS[$IX]=$((P-1)); LEN[$IX]=$L; done < layout.txt

while read T
  do    unset CRS L
        for i in ${!POS[@]}
          do    L=$L${T:$CRS:$((${POS[$i]}-CRS))}"~"${T:${POS[$i]}:${LEN[$i]}}"~"
                CRS=$((${POS[$i]}+${LEN[$i]}))
          done
        L=${L#\~}
        L=${L//~~/\~}
        L=$L${T:$CRS}
        printf "%s\n" $L
  done < abc.txt
11~01~0116~03~15100000000000000
11~01~0116~03~15100000000000000

Thanks this looks perfect ,
when I run it in ksh it gives error for IX, I defined IX=0 but still doesn't work

IX++: bad number

any idea why ?

ksh93 should know the arithmetic evaluation within (( ... )) . What be your ksh version?

Replace the post increment command by any other that will increment IX by 1.