Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a file with several unsorted things in one line which I want to put into a new file This is an example of part of the file I have:

X1314448: SaMi|SM_g2554.t1 SaMi|SM_g5072.t1 Des|Des_g3808.t1 Dul|Dul_comp50786_c0_seq1-1 Nig|Nig_comp88811_c0_seq2-1 AB|AB0003DMP400018076_AB0003DMT400026495 Phy|Phy_comp35647_c0_seq1-1 SWtf|SW_g27807.t1 Tom|Solyc02g077050.2.1
X1314810: Des|Des_g33587.t1 Nig|Nig_comp84357_c0_seq1-1 AB|AB0003DMP400020961_AB0003DMT400030857 Phy|Phy_comp33112_c0_seq1-1 SaMi|SM_g27352.t1 SWtf|SW_g21774.t1 TAIR|AT4G14930.1 Tom|Solyc06g054250.2.1 Dul|Dul_comp63657_c0_seq2-1
X1327159: AB|AB0003DMP400016823_AB0003DMT400024599 AB|AB0003DMP400017933_AB0003DMT400026257 Dul|Dul_comp58749_c0_seq2-1

X1330513: Des|Des_g36886.t1 AB|AB0003DMP400049952_AB0003DMT400073802 SWtf|SW_g16502.t1

X132738: Des|Des_g491.t1 Des|Des_g6171.t1 Dul|Dul_comp57659_c0_seq2-1 Dul|Dul_comp57659_c0_seq3-1 Dul|Dul_comp57659_c0_seq4-1 Ni                                                                       g|Nig_comp93106_c3_seq1-1 Nig|Nig_comp93106_c3_seq2-1 AB|AB0003DMP400005485_AB0003DMT400007895 AB|AB0003DMP400021388_PGS                                                                       C0003DMT400031553 Phy|Phy_comp61931_c0_seq1-1 Phy|Phy_comp61931_c0_seq2-1 Phy|Phy_comp61931_c0_seq3-1 Phy|Phy_comp61931_c0_seq4-1                                                                        RICE|LOC_Os08g43334.1 RICE|LOC_Os08g43334.2 RICE|LOC_Os09g35790.1 RICE|LOC_Os09g35790.2 SaMi|SM_g30888.t1 SaMi|SM_g5888.t1 SWtf|SW                                                                       _g17547.t1 SWtf|SW_g33717.t1 Des|Des_g47565.t1 SaMi|SM_g6027.t1 SWtf|SW_g42019.t1 TAIR|AT5G62020.1 Tom|Solyc03g026020.2.1 TAIR|AT4                                                                       G11660.1

What I want is to have the first part, "X1314448:" followed by by "Des|Des_g3808.t1”. And if there is another “Des_xxx” (in some cases there are more than one, like in the second to last line), I want that to be included as well, followed by the “AB|AB00…” in the output file, but since it is an unsorted list I am uncertain how to sort out the three different parts I want while still keeping them on the same line (keeping them linked to each other). I am also not sure how to get several matches on one line like this.

So for the first line, the output should be:

X1314448: Des|Des_g3808.t1 AB|AB0003DMP400018076_AB0003DMT400026495 

For the second to last last one:

X1330513: Des|Des_g36886.t1 AB|AB0003DMP400049952_AB0003DMT400073802

for the last one:

X132738: Des|Des_g491.t1 Des|Des_g6171.t1 Des|Des_g47565.t1 AB|AB0003DMP400005485_AB0003DMT400007895 AB|AB0003DMP400021388_PGSC0003DMT400031553

I think the main problem is the last line. I also want to be able to modify the file to have the "Dul|..." included as well.


Solution:

After working on it a bit I ended up with: 1 - Save this script as FastaToTbl and make it executable (chmod 744 FastaToTbl):

if (substr($1,1,1)==">")
       if (NR>1)
             printf "\n%s\t", substr($0,2,length($0)-1)
      else
         printf "%s\t", substr($0,2,length($0)-1)
       else
          printf "%s", $0
}END{printf "\n"}'  "$@"

2 - make and a second file containing this script: Use FastaToTbl combined with this script to extract the IDs from file1 and the sequences from file2:

 ./mktbl file1[contains FASTA sequences] |
  perl -ne 'chomp;@a=split(/\t/); $k{$a[0]}=$a[1]; ## Collect the sequences
                                               ## $k{ID}=SEQUENCE
      END{open(A,"File02[contains my data that is missing FASTA sequences (ID file)]");   ## Open ID file
         while(<A>){         ## and process it line by line
           @a=split(/\s+/);  ## Gather the IDs in array @a
           print shift(@a);  ## Print the first element (Jan123:)
           print "$_ $k{$_}\n" for @a; ## Print each ID and its seq
 }}'
share|improve this question

2 Answers 2

awk '/^ *$/ {next;}; NR>1 {print bufline;};
  {bufline=$1 " ";
    for (i=2;i<=NF;i++)
      { if ($i ~ "^Des\\|" || $i ~ "^AB\\|") bufline=bufline sprintf("%s ",$i);
        if ($i ~ "^Dul\\|") dul=$i;
      };
  };
  END {print bufline " " dul;}' inputfile
share|improve this answer
    
After working on it a bit I ended up with a working solution! Thank you for your help! –  Stenemo Jun 16 '13 at 14:55
    
@Stenemo Then you should accept this answer in order to mark your question solved. –  Hauke Laging Jun 16 '13 at 15:31

Wouldn't this work for you:

sort -k 2

Basically, sort by default will define columns by white spaces, you can change this is option -t. In this case I'm letting it know to sort by the second field. And from a first look it gets what you want.

If you want to make consecutive sort, you can still use sort adding extra -k options. Fromt the man page:

   -k, --key=KEYDEF
          sort via a key; KEYDEF gives location and type

KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where F is a field number and C a character position in the field; both are origin 1, and the stop position defaults to the line's end

X1327159: AB|AB0003DMP400016823_AB0003DMT400024599 AB|AB0003DMP400017933_AB0003DMT400026257 Dul|Dul_comp58749_c0_seq2-1
X1314810: Des|Des_g33587.t1 Nig|Nig_comp84357_c0_seq1-1 AB|AB0003DMP400020961_AB0003DMT400030857 Phy|Phy_comp33112_c0_seq1-1 SaMi|SM_g27352.t1 SWtf|SW_g21774.t1 TAIR|AT4G14930.1 Tom|Solyc06g054250.2.1 Dul|Dul_comp63657_c0_seq2-1
X1330513: Des|Des_g36886.t1 AB|AB0003DMP400049952_AB0003DMT400073802 SWtf|SW_g16502.t1
X132738: Des|Des_g491.t1 Des|Des_g6171.t1 Dul|Dul_comp57659_c0_seq2-1 Dul|Dul_comp57659_c0_seq3-1 Dul|Dul_comp57659_c0_seq4-1 Ni 
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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