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
one
containsAAAAABB
) 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
foreach
loop). If we save the transformed data to be output into an array of arrays (AoA), then we can justpush
thelength
values 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::Printer
which can be used from the command line as-MDDP
to visualize data structures.> /tmp/output.txt
Next - try this longish one-liner that uses
DDP
andp
to show the structure of the array we create:In the
BEGIN
block welocal
-ize@ARGV
;shift
off the first file (our version of yourTMP
file) -{local @ARGV=shift}
is almost a perl idiom for handling multiple input files; we thensplit
it inside an anonymous array constructor ([]
) andmap { }
that into the@tmp
array which we display withDDP
'sp()
function. Once we are out of theBEGIN
block, the implicitwhile (<>){ ... }
that we get with perl's-n
command 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$name
variable; thewhile
continues and wepush
$name
and thelength
of any line that does not start with>
(if !/^>/
) wrapped as elements of an anonymous array[]
into the@out
array 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 nestedfor
loop topush
things 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
exit
to 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::All
because 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 ...