1

I have a file like this.

>;1;
AACTCTGGGACAATGGCACACGGGAAACAGATAATGAACGATCAGCACAGGGAACTAGCG
>;2;
AACTCTGGGACAATGGCACACGGGAAACAGATAATGAACGATCAGCACAGGGAACTAGCG
>;3;
AACTCTGGGACAATGGCACACGGGAAACAGATAATGAACGATCAGCACAGGGAACTAGCG

I would like to change each number to a corresponding string.

I wrote the following Perl program but I don't know what is wrong with it.

%lista2 = (
    1  => "CAT00.3",
    2  => "CAT43.1",
    3  => "CAT40.3"
);

open(OA, ">file2.txt");

foreach $key ( keys %lista2 ) {

    open(SAL, "file.txt");

    while ( <SAL> ) {
        chomp;

        if( />/ ) {

            @w = split("\t");   
            $r = 0;
            s/\;//g;

            if ( /%lista2[i]/ ) {    
                print OA "$_ $lista2{$key}\n" ;
                $r = 1;
            }
        }
    }
}

close(SAL);
close(OA);

I want to get this

>CAT00.3
AACTCTGGGACAATGGCACACGGGAAACAGATAATGAACGATCAGCACAGGGAACTAGCG
>CAT43.1
AACTCTGGGACAATGGCACACGGGAAACAGATAATGAACGATCAGCACAGGGAACTAGCG
>CAT40.3
AACTCTGGGACAATGGCACACGGGAAACAGATAATGAACGATCAGCACAGGGAACTAGCG

But I don't know how do that.

Borodin
  • 126,100
  • 9
  • 70
  • 144

1 Answers1

2

Well you were in the right direction, I guess. But somewhere along the path you we're lost and it seems like randomly tried to run in any direction. There are a lot of things wrong in your code.

For instance it's funny how you can have those two lines

        if ( /%lista2[i]/ ) {    
            print OA "$_ $lista2{$key}\n" ;

having one correct attempt accessing a has value ($lista2{$key}) and a totally wrong one (%lista2[i]) so close together.

Then, since you're only printing to OA if ("/$lista2{$key}/"), you'd completely eradicate all other lines in the output. Your example indicates, you don't want that.

Furthermore change the loop nesting. Instead of opening the file over and over again, open it once, iterate over the lines and in each such iteration iterate over the hash keys. Your way wasn't strictly wrong but opening and closing files doesn't come cheap, you know. And speaking of closing files: You didn't close SAL in the body of your outer loop, but that's where you reopen it.

And use at least some very basic error handling. Check if open has failed. A wrong file name and the program fails without any indication why. Make your life easier.

Why use chomp() if you later append an \n to the output anyway and make a line of it again? Skip that.

I don't know how to interpret these lines:

        @w = split("\t");   
        $r = 0;
        s/\;//g;

Is that some leftovers? They don't do anything useful.

Last but not least it's recommended to use strict; and possibly use warnings; to get pointers on problematic spots.

Here's one that passes your example.

#!/usr/bin/perl

use strict;
use warnings;

my %lista2 =
(
  1  => "CAT00.3",
  2  => "CAT43.1",
  3  => "CAT40.3"
);

if (!open(OA, ">file2.txt")) {
 die($!);
}
if (!open(SAL, "file.txt")) {
  die($!);
}

foreach my $line (<SAL>) {
  foreach my $key (keys(%lista2)) {
    if ($line =~ s/^>;$key;$/>$lista2{$key}/) {
      last;
    }
  }
  print(OA $line);
}

close(SAL);
close(OA);

In fact, in the core it can be simplified to a pattern replacement. No splitting or anything is needed. But patterns might be confusing if you're a beginner.

I also raised the level of verbosity to make things clearer.

sticky bit
  • 36,626
  • 12
  • 31
  • 42