0

I have a genotype file with 5 fields (5th field width= 200000 values [zeros and ones]):

MA,30009,4,4,000010000111101011111000110100000000 .......
ME,30067,3,2,000010000111101011111000110100000000 .......
MI,30032,7,8,000010000111101011111000110100000000 .......

And I want to split the last field into multiple columns every 2 values (ncol = 100000). I want the output to be as below:

MA,30009,4,4,00,00,10,00,01,11,10,10,11,11,10,00,11,01,00,00,00,00 .......
ME,30067,3,2,00,00,10,00,01,11,10,10,11,11,10,00,11,01,00,00,00,00 .......
MI,30032,7,8,00,00,10,00,01,11,10,10,11,11,10,00,11,01,00,00,00,00 .......

awk? gwak? sed?

Any help?? Thanks in advance

1
awk 'BEGIN{FS=OFS=","}{gsub(/../,"&,",$NF)}1' file
  • BEGIN{FS=OFS=","} sets field separators to ,.
  • {gsub(/../,"&,",$NF)} appends , to every 2 chars in the last field ($NF).
  • 1 prints the resulting line.

Result:

MA,30009,4,4,00,00,10,00,01,11,10,10,11,11,10,00,11,01,00,00,00,00,

If you want to remove the trailing comma the above command produces, remove it with an extra sub function:

awk 'BEGIN{FS=OFS=","}{gsub(/../,"&,",$NF);sub(/,$/,"",$NF)}1' file
MA,30009,4,4,00,00,10,00,01,11,10,10,11,11,10,00,11,01,00,00,00,00
1

You could use Sed with a loop:

$ sed -E -e :a -e 's/(,[^,]{2})([^,]{1,})$/\1,\2/;ta' file
MA,30009,4,4,00,00,10,00,01,11,10,10,11,11,10,00,11,01,00,00,00,00
ME,30067,3,2,00,00,10,00,01,11,10,10,11,11,10,00,11,01,00,00,00,00
MI,30032,7,8,00,00,10,00,01,11,10,10,11,11,10,00,11,01,00,00,00,00

(I have a feeling there's a neater way to do this, starting from $ and working backwards - but I can't quite put my finger on it). The -E (extended regex) mode is not essential - it just simplifies the escaping.

Alternatively with Perl:

$ perl -F, -lne '$last = pop @F; print join ",", @F, $last =~ m/(..)/g' file
MA,30009,4,4,00,00,10,00,01,11,10,10,11,11,10,00,11,01,00,00,00,00
ME,30067,3,2,00,00,10,00,01,11,10,10,11,11,10,00,11,01,00,00,00,00
MI,30032,7,8,00,00,10,00,01,11,10,10,11,11,10,00,11,01,00,00,00,00
0

GNU awk We merge the last field into the second last and then decrement the field count.

gawk -F ',' -v OFS="," '{
  $4 = $4 gensub(/../, ",&", "g", $5)
}NF--' file

With awk

awk '
  BEGIN { OFS = FS = "," }
  gsub(/../, FS "&", $5) {
    print $1, $2, $3, $4 $5
  }
' file

GNU sed with extended mode

sed -Ee '
  s/,/\n/4;ta
  :a
    s/\n,/,/;t
    s/..(,..)*$/,&/
  ta
' file

Perl where we unpack the field 5th two characters at a time.

perl -F, -lape '$_ = join ",", @F[0..3], unpack "(A2)*", $F[4]' file 

Another way using Perl

perl -F, -lane 'print reverse pop(@F) =~ s/(..)/,$1/gr, join ",", @F' file
perl -lpe 's/^.*[^,]\K,(.*)/$1 =~ s|(..)|,$1|gr/e' file

Using posix sed (\n) on rhs is symbolic. Replace it by an escaped newline)

sed -e '
  s/,/\n/4;h;s/\n.*//;x
  s/.*\n//;s/../,&/g;H;x
  s/\n//
' file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.