I've got the follow function inside a perl script:
sub fileSize {
my $file = shift;
my $opt = shift;
open (FILE, $file) or die "Could not open file $file: $!";
$/ = ">";
my $junk = <FILE>;
my $g_size = 0;
while ( my $rec = <FILE> ) {
chomp $rec;
my ($name, @seqLines) = split /\n/, $rec;
my $sec = join('',@seqLines);
$g_size+=length($sec);
if ( $opt == 1 ) {
open TMP, ">>", "tmp" or die "Could not open chr_sizes.log: $!\n";
print TMP "$name\t", length($sec), "\n";
}
}
if ( $opt == 0 ) {
PrintLog( "file_size: $g_size", 0 );
}
else {
print TMP "file_size: $g_size\n";
close TMP;
}
$/ = "\n";
close FILE;
}
Input file format:
>one
AAAAA
>two
BBB
>three
C
I have several input files with that format. The line beginning with ">" is the same but the other lines can be of different length. The output of the function with only one file is:
one 5
two 3
three 1
I want to execute the function in a loop with this for each file:
foreach my $file ( @refs ) {
fileSize( $file, 1 );
}
When running the next iteration, let's say with this file:
>one
AAAAABB
>two
BBBVFVF
>three
CS
I'd like to obtain this output:
one 5 7
two 3 7
three 1 2
How can I modify the function or modify the script to get this? As can be seen, my function append the text to the file
Thanks!
I've left out your options and the file IO operations and have concentrated on showing a way to do this with an array of arrays from the command line. I hope it helps. I'll leave wiring it up to your own script and subroutines mostly up to to you :-)
Running this one liner against your first data file:
gives this output:
Substituting the second version or instance of the data file (i.e where record
onecontainsAAAAABB) gives the expected results as well.In your script above, you save to an output file in this format. So, to append columns to each row in your output file, we can just munge each of your data files in the same way (with any luck this might mean things can be converted into a function that will work in a
foreachloop). If we save the transformed data to be output into an array of arrays (AoA), then we can justpushthelengthvalues we get for each data file string onto the corresponding anonymous array element and then print out the array. Voilà! Now let's hope it works ;-)You might want to install
Data::Printerwhich can be used from the command line as-MDDPto visualize data structures.> /tmp/output.txtNext - try this longish one-liner that uses
DDPandpto show the structure of the array we create:In the
BEGINblock welocal-ize@ARGV;shiftoff the first file (our version of yourTMPfile) -{local @ARGV=shift}is almost a perl idiom for handling multiple input files; we thensplitit inside an anonymous array constructor ([]) andmap { }that into the@tmparray which we display withDDP'sp()function. Once we are out of theBEGINblock, the implicitwhile (<>){ ... }that we get with perl's-ncommand line switch takes over and reads in the remaining file from@ARGV; we process lines starting with>- stripping the leading character and assigning the string that follows to the$namevariable; thewhilecontinues and wepush$nameand thelengthof any line that does not start with>(if !/^>/) wrapped as elements of an anonymous array[]into the@outarray which we display withp()as well (in theEND{}block so it doesn't print inside our implicitwhile()loop). Phew!!See the AoA that results as a gist @Github.
END{...}block (add a nestedforloop topushthings around) and put this all together to produce the output we want.This one liner:
produces:
We'll have to convert that into a script :-)
The script consists of three rather wordy subroutines that reads the log file; parses the datafile ; merges them. We run them in order. The first one checks to see if there is an existing log and creates one and then does an
exitto skip any further parsing/merging steps.You should be able to wrap them in a loop of some kind that feeds files to the subroutines from an array instead of fetching them from
STDIN. One caution - I'm usingIO::Allbecause it's fun and easy!The subroutines do all the work here - you can likely find ways to shorten; combine; improve them. Is this a useful approach for you?
I hope this explanation is clear and useful to someone - corrections and comments welcome. Probably the same thing could be done with place editing (i.e with
perl -pie '...') which is left as an exercise to those that follow ...