Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Add data to input files

by micky744monk (Novice)
on Sep 18, 2011 at 18:47 UTC ( [id://926649]=perlquestion: print w/replies, xml ) Need Help??

micky744monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks. I'm stuck with a problem and I tried all the possibilities I had in mind. Now I hope someone can give me a hands. Basically my problem is: I have a tab delimited text file 1 with 5 different fields. From this file I need the field five associated to the field 1. Now I have a tab delimited text file 2. Here I have 15 fields and I want to add the info of field 5 from file 1, if the field 11 (of file 2) is equal to the field 1 of file 1. More I just want to add the infos, not to obtain a new file with only the lines with all the info in it. What I have done is to obtain an hash from file 1. Then when going to file 2 I compare the field 11 with all the keys of the hash and if I find the correspondence I print on a new file the line together with the value of the hash. In this way I get only a new out file with only the lines where I have added the new field, but still I want all of them Anyone has any idea about what I'm doing wrong? Guess my problem comes with this code, where I could put an else and print the line $_, but this is printed for all the keys I have in the hash.....too many!
elsif ($rsfound =~ m/^rs[0-9]/i) {foreach my$key (keys(%out)) { if ( $rsfound eq $key ) {print OUTFILE "$_\t $out{$key}\n";} }
Hope you can help me out a bit! Cheers

Replies are listed 'Best First'.
Re: Add data to input files
by keszler (Priest) on Sep 18, 2011 at 19:12 UTC

    Maybe I'm not quite understanding, it seems to me that the procedure should be either

    1. Read file 2 (not 1) into a hash
    2. For each line of file 1
      • Compare; if match add info to hash
    3. Print hash to file

    or, e.g. if file 2 is too large:

    1. Read file 1 into a hash
    2. For each line of file 2
      • Compare; if match add info to line
      • Print line to file (regardless of match)
      Summarizing File 1 contains Field1 Field2 Field3 Field4 Field5 File 2 contains Field1..Field15 I need to compare Field11 from file 2 with field1 from file 1 and if match add Field5 from file1. If it doesn't match I need to print the line in any case. The problem is to print the line to file regardless of the match, since the code I posted above.....it will write the line as many times as they key I have in the hash obtained from file 1 I hope to have been clearer. Thanks for your idea!
Re: Add data to input files
by pvaldes (Chaplain) on Sep 18, 2011 at 19:02 UTC

    I have a tab delimited text file 1 with 5 different fields. From this file I need the field five associated to the field 1

    open my $file, '<', "file1"; while ($file){ chomp; my ($one,$too,$tree,$fool,$flin) = split /\t+/, $_, 5; print $one, " ", $flin; }

    From this file I need the field five associated to the field 1

    ok, after read again I see that you want a hash... then define a hash first and change the print line for this line

    $hash{$one} = $flin;
Re: Add data to input files
by poj (Abbot) on Sep 18, 2011 at 21:15 UTC
    I don't think you need to test the keys, just print what you have
    } elsif ( $rsfound =~ m/^rs[0-9]/i ){ print OUTFILE "$_\t $out{$rsfound}\n"; }
    poj
Re: Add data to input files
by pvaldes (Chaplain) on Sep 18, 2011 at 19:51 UTC
    Now I have a tab delimited text file2 with 15 fields and I want to add the info of field 5 from file1, if the field 11 (of file 2) is equal to the field 1 of file 1.

    this is more tricky, temptatively and untested, open file 2 first as usual...

    for my $key ( keys %hash ) { while ($file2){ if ( / \a .*?\t # field 1 of file 2 .*?\t # field 2 of file 2 .*?\t # field 3 of file 2 .*?\t # field 4 of file 2 .*?\t # field 5 of file 2 .*?\t # field 6 of file 2 .*?\t # field 7 of file 2 .*?\t # field 8 of file 2 .*?\t # field 9 of file 2 .*?\t # field 10 of file 2 $key \t .*?\t # field 12 of file 2 .*?\t # field 13 of file 2 .*?\t # field 14 of file 2 .*\z # field 15 of file 2 /x) { do something...} else {next} }
      I did not understand your solution Actually the code till here is
      while (<MYINFILE>) { chomp ($_); @line = split (/\t/, $_); $rsfound = $line[11] ; my$loc = $line[0] ; if ($loc =~ m/location/i) {print OUTFILE "$_\t YRI_iHs\n" ; } elsif ($rsfound =~ m/^rs[0-9]/i) {foreach my$key (keys(%out)) { if ( $rsfound eq $key ) {print OUTFILE "$_\t $out{$key}\n";} }
      This script show me only the line of file 2 where i find the match with the key of the hash %out. I actually need to print all the lines, even the ones without the match. Sorry from file 1 I go the hash %out with field1 as keys and field5 as values
        If I understand your stated goal, I think you just need to move the print statement for the lines from file2 so that it's outside the conditional -- that is, you are going to print every line from file2, but you will only be altering the contents of some of the lines.

        Also, since you have a hash for the relevant values from file1, you don't need to loop over all the hash keys when reading each line from file2. You just need to test of the field-11 value from file2 exists as a hash key from file1.

        Putting those two things together:

        use strict; use warnings; my ( $file1, $file2 ) = ( 'file1_name_here', 'file2_name_here' ); # read hash keys and values from file1: open( F, '<', $file1 ) or die "$file1: $!\n"; my %mods; while (<F>) { chomp; my ( $key, $val ) = ( split /\t/ )[0,4]; $mods{$key} = $val; } close F; # read and rewrite file2, altering certain lines as needed open( IN, '<', $file2 ) or die "$file2: $!\n"; open( OUT, '>', "$file2.new" ) or die "$file2.new: $!\n"; while (<IN>) { chomp; my ( $loc, $chk ) = ( split /\t/ )[0,11]; # or should it be [0,10 +]? if ( $loc =~ /location/ ) { # modify some input lines as needed $_ .= "\t YRI_iHs\n"; } elsif ( exists( $mods{$chk} )) { $_ .= "\t$mods{$chk}\n"; } print OUT; # print every input line to output file } close IN; close OUT; # you could rename the output to replace the original... # rename "$file2.new", $file2; # (but you might want to check the output first)
        If that's not what you meant, then you'll need to explain your goal more clearly, possibly with some sample data.

        (updated to fix typo in last comment line)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://926649]
Approved by dHarry
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (3)
As of 2024-04-26 03:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found