perl: print output of subroutine to file - perl

How to write the output of a subroutine to file?
my $logfile="C:/Test/report_p3.txt";
open(my $tt, ">",$logfile) or die "Can not open file";
foreach (#files)
{
if (($_ ne ".") && ($_ ne ".."))
{
&getinfo($logdir."/".$_);
print $tt &getinfo; #Here, I wanna pass the output to the handler
}
}
close $tt;
on standard output, &getinfo prints correctly the output.

Open a filehandle that outputs into a variable, and select it.
After that all output going into STDOUT will be caught in the variable.
Here is an example:
sub output {
print "test\n";
}
my $out;
open VAROUT, '>', \$out;
select VAROUT;
output();
select STDOUT;
printf "output: %s\n", $out;

Is it really necesssary, that the subroutine, whose output you want to pass actually prints something?
Usually you should simply make your sub return a string and have the caller decide where to output it.
my $logfile="C:/Test/report_p3.txt";
open(my $tt, ">",$logfile) or die "Can not open file";
sub get_log {
return "some text to log";
}
sub log_write {
my $log_fh = shift;
print $log_fh get_log() . "\n";
}
log_write($tt); # prints to file handle from $tt
log_write(STDOUT); # prints to STDOUT

Related

how to combine the code to make the output is on the same line?

Can you help me to combine both of these progeam to display the output in a row with two columns? The first column is for $1 and the second column is $2.
Kindly help me to solve this. Thank you :)
This is my code 1.
#!/usr/local/bin/perl
#!/usr/bin/perl
use strict ;
use warnings ;
use IO::Uncompress::Gunzip qw(gunzip $GunzipError);
my $input = "par_disp_fabric.all_max_lowvcc_qor.rpt.gz";
my $output = "par_disp_fabric.all_max_lowvcc_qor.txt";
gunzip $input => $output
or die "gunzip failed: $GunzipError\n";
open (FILE, '<',"$output") or die "Cannot open $output\n";
while (<FILE>) {
my $line = $_;
chomp ($line);
if ($line=~ m/^\s+Timing Path Group \'(\S+)\'/) {
$line = $1;
print ("$1\n");
}
}
close (FILE);
This is my code 2.
my $input = "par_disp_fabric.all_max_lowvcc_qor.rpt.gz";
my $output = "par_disp_fabric.all_max_lowvcc_qor.txt";
gunzip $input => $output
or die "gunzip failed: $GunzipError\n";
open (FILE, '<',"$output") or die "Cannot open $output\n";
while (<FILE>) {
my $line = $_;
chomp ($line);
if ($line=~ m/^\s+Levels of Logic:\s+(\S+)/) {
$line = $1;
print ("$1\n");
}
}
close (FILE);
this is my output for code 1 which contain 26 line of data:
**async_default**
**clock_gating_default**
Ddia_link_clk
Ddib_link_clk
Ddic_link_clk
Ddid_link_clk
FEEDTHROUGH
INPUTS
Lclk
OUTPUTS
VISA_HIP_visa_tcss_2000
ckpll_npk_npkclk
clstr_fscan_scanclk_pulsegen
clstr_fscan_scanclk_pulsegen_notdiv
clstr_fscan_scanclk_wavegen
idvfreqA
idvfreqB
psf5_primclk
sb_nondet4tclk
sb_nondetl2tclk
sb_nondett2lclk
sbclk_nondet
sbclk_sa_det
stfclk_scan
tap4tclk
tapclk
The output code 1 also has same number of line.
paste is useful for this: assuming your shell is bash, then using process substitutions
paste <(perl script1.pl) <(perl script2.pl)
That emits columns separated by a tab character. For prettier output, you can pipe the output of paste to column
paste <(perl script1.pl) <(perl script2.pl) | column -t -s $'\t'
And with this, you con't need to try and "merge" your perl programs.
To combine the two scripts and to output two items of data on the same line, you need to hold on until the end of the file (or until you have both data items) and then output them at once. So you need to combine both loops into one:
#!/usr/bin/perl
use strict ;
use warnings ;
use IO::Uncompress::Gunzip qw(gunzip $GunzipError);
my $input = "par_disp_fabric.all_max_lowvcc_qor.rpt.gz";
my $output = "par_disp_fabric.all_max_lowvcc_qor.txt";
gunzip $input => $output
or die "gunzip failed: $GunzipError\n";
open (FILE, '<',"$output") or die "Cannot open $output\n";
my( $levels, $timing );
while (<FILE>) {
my $line = $_;
chomp ($line);
if ($line=~ m/^\s+Levels of Logic:\s+(\S+)/) {
$levels = $1;
}
if ($line=~ m/^\s+Timing Path Group \'(\S+)\'/) {
$timing = $1;
}
}
print "$levels, $timing\n";
close (FILE);
You still haven't given us one vital piece of information - what does the input data looks like. Most importantly, are the two pieces of information you're looking for on the same line?
[Update: Looking more closely at your regexes, I see it's possible for both pieces of information to be on the same line - as they are both supposed to be the first item on the line. It would be helpful if you were clearer about that in your question.]
I think this will do the right thing, no matter what the answer to your question is. I've also added the improvements I suggested in my answer to your previous question:
#!/usr/bin/perl
use strict ;
use warnings ;
use IO::Uncompress::Gunzip qw(gunzip $GunzipError);
my $zipped = "par_disp_fabric.all_max_lowvcc_qor.rpt.gz";
my $unzipped = "par_disp_fabric.all_max_lowvcc_qor.txt";
gunzip $zipped => $unzipped
or die "gunzip failed: $GunzipError\n";
open (my $fh, '<', $unzipped) or die "Cannot open '$unzipped': $!\n";
my ($levels, $timing);
while (<$fh>) {
chomp;
if (m/^\s+Levels of Logic:\s+(\S+)/) {
$levels = $1;
}
if (m/^\s+Timing Path Group \'(\S+)\'/) {
$timing = $1;
}
# If we have both values, then print them out and
# set the variables to 'undef' for the next iteration
if ($levels and $timing) {
print "$levels, $timing\n";
undef $levels;
undef $timing;
}
}
close ($fh);

Why am I getting error print() on closed filehandle in Perl

I am trying to write output to one C file but I'm getting an error about print() on closed filehandle.
my $fileoutput="output.c";
open OUTFILE, "> $fileoutput" or die $!;
for my $i (keys%hash) {
# grep for c file output and compare
# with xml key print both key and values
if (grep $_ eq $i,#c_result_array) {
if (defined $hash{$i}) {
my #values = $hash{$i};
print OUTFILE $i . "=> #values";
print OUTFILE "\n";
}
close OUTFILE;
}
}
You close the output file inside the for loop. By the second iteration, the file handle has been closed. You have to close the file once the loop has run to completion.
Also, bareword file handles have package scope which comes with all the disadvantages of global variables. Use lexical file handles.
Also, especially if the name of the file you are opening is coming from the outside, use the three argument form of open, and always include the name of the file in error messages.
Finally, presumably, $hash{$i} contains an array reference, so you have to dereference it if you are going to interpolate its contents into a string.
my $fileoutput = "output.c";
open my $OUTFILE, '>', $fileoutput
or die "Failed to open '$fileoutput': $!";
for my $i (keys %hash) {
#grep for c file output and compare with xml key print both key and values #
if (grep $_ eq $i, #c_result_array) {
if(defined $hash{$i}) {
my #values = #{ $hash{$i} };
print $OUTFILE "$i => #values\n";
}
}
}
close $OUTFILE
or die "Failed to close '$fileoutput': $!";

Add headings to the a text file in perl

I have a text file with the following lines as example
This is line
This is line with test
This is ine with 2test
This is line 2
This is line 3
This is line with 3test
This is line 4
This is line with 4test
Now I want a code to change the text file as follows:
Lines with test
This is line with test
This is ine with 2test
This is line with 3test
This is line with 4test
Lines without test
This is line
This is line 2
This is line 3
This is line 4
I am using the following code. I am assuming my code would print the title with every line but I am not able to execute the code due to some errors.
Can you please help me?
#!/usr/bin/perl
use strict;
use warnings;
open(FH, '<filetest.txt');
my #queues = <FH>;
close(FH);
open(OFH,'>testfile.txt');
my $name;
foreach $name(#queues)
{
if($name =~ 'test')
{
print OFH "Lines with test\n";
print OFH $1;
}
else{
print OFH "Lines without test\n";
print OFH $1;
}
close(OFH);
}
Note: I corrected the error to remove the syntax errors but still there is nothing being written to the file testfile.txt
Have a try with:
#!/usr/bin/perl
use strict;
use warnings;
my $infile = 'filetest.txt';
my $outfile = 'testfile.txt';
# use 3-arg open and if open succeeded
open my $fh_in, '<', $infile or die "Unable to open file '$infile' for reading: $!";
my #with_test;
my #without_test;
while (<$fh_in>) {
if (/test/) {
push #with_test, $_;
} else {
push #without_test, $_;
}
}
close $fh_in;
open my $fh_out, '>', $outfile or die "Unable to open file '$outile' for writting: $!";
print $fh_out "Lines with test\n";
print $fh_out #with_test;
print $fh_out "Lines without test\n";
print $fh_out #without_test;
close $fh_out;
I haven't tested this. The idea is to write the "with test" lines to the file immediately
The "without test" lines are stored (in an array called "without") until the end of the program and then written
#!/usr/bin/perl
use strict;
use warnings;
open(FH, '<filetest.txt');
my #queues = <FH>;
close(FH);
open(OFH,'>testfile.txt');
my $name;
my #without=();
foreach $name(#queues)
{
if($name =~ 'test')
{
print OFH $name;
}
else{
push #without, $name;
}
print OFH "\n\nlines without\n";
print OFH #without;
}
also you should add a local $/ before reading the file handle.
check this out:
how to read the whole file.
the match format should be like this: if($somestr =~ /#/).
and you shouldn't close the filehandle in the loop.
#!/usr/bin/perl
use strict;
use warnings;
local $/;
open(FH, 'file#.txt');
my $s;
$s = <FH>;
close(FH);
open(FH, '>file#.txt');
my #queues = split(/\n/, $s);
my #arr;
my #arr2;
for($s=0; $s<$#queues+1; $s++)
{
if($queues[$s] =~ /#/)
{
push(#arr, $queues[$s]."\n");
}
else
{
push(#arr2, $queues[$s]."\n");
}
}
print FH "lines with #\n";
print FH #arr;
print FH "lines without #\n";
print FH #arr2;

How to read from a file and direct output to a file if a file name is given in the command line, and printing to console if no argument given

I made a file, "rootfile", that contains paths to certain files and the perl program mymd5.perl gets the md5sum for each file and prints it in a certain order. How do I redirect the output to a file if a name is given in the command line? For instance if I do
perl mymd5.perl md5file
then it will feed output to md5file. And if I just do
perl mydm5.perl
it will just print to the console.
This is my rootfile:
/usr/local/courses/cs3423/assign8/cmdscan.c
/usr/local/courses/cs3423/assign8/driver.c
/usr/local/courses/cs3423/assign1/xpostitplus-2.3-3.diff.gz
This is my program right now:
open($in, "rootfile") or die "Can't open rootfile: $!";
$flag = 0;
if ($ARGV[0]){
open($out,$ARGV[0]) or die "Can't open $ARGV[0]: $!";
$flag = 1;
}
if ($flag == 1) {
select $out;
}
while ($line = <$in>) {
$md5line = `md5sum $line`;
#md5arr = split(" ",$md5line);
if ($flag == 0) {
printf("%s\t%s\n",$md5arr[1],$md5arr[0]);
}
}
close($out);
If you don't give a FILEHANDLE to print or printf, the output will go to STDOUT (the console).
There are several way you can redirect the output of your print statements.
select $out; #everything you print after this line will go the file specified by the filehandle $out.
... #your print statements come here.
close $out; #close connection when done to avoid counfusing the rest of the program.
#or you can use the filehandle right after the print statement as in:
print $out "Hello World!\n";
You can print a filename influenced by the value in #ARGV as follows:
This will take the name of the file in $ARGV[0] and use it to name a new file, edit.$ARGV[0]
#!/usr/bin/perl
use warnings;
use strict;
my $file = $ARGV[0];
open my $input, '<', $file or die $!;
my $editedfile = "edit.$file";
open my $name_change, '>', $editedfile or die $!;
if ($input eq "md5file"){
while ($in){
# Do something...
print $name_change "$_\n";
}
}
Perhaps the following will be helpful:
use strict;
use warnings;
while (<>) {
my $md5line = `md5sum $_`;
my #md5arr = split( " ", $md5line );
printf( "%s\t%s\n", $md5arr[1], $md5arr[0] );
}
Usage: perl mydm5.pl rootfile [>md5file]
The last, optional parameter will direct output to the file md5file; if absent, the results are printed to the console.

I am looking to input a file in Perl and then export it changed

I am looking to change a txt file in Perl, by input the file, then exporting it with a blank line in between the existing ones. How do i do this? I have this so far:
#!/usr/bin/perl;
use strict;
use warnings;
print "Hi! This Program Will Input\n";
print "The File and Export A New\n";
print "File With A Blank Line In-Between\n";
print "Every Other Line\n";
sleep(2);
print "\n";
print "\n";
print "Working\n";
print "\n";
sleep(1);
print "\n";
print "Working\n";
sleep(1);
open(my $in, "<", "input.txt") or die "Can't Open Input.txt: $!";
open(my $out, ">", "output.txt") or die "Can't Open Output.txt: $!";
my #lines = <$in>;
while (<$in>) {
print $out
print $lines[$#lines];
print " ";
}
print "Completed Successfully!!\n";
print "\n";
print "Outputed to Output.txt\n";
close $in or die "$in: $!"
What am i missing? I am only just learning Perl so i do not know much at all.
The problem is the while loop. You can iterate over the filehandle with the while, or do a loop over the array where you saved the file content with for. Iterators can be processed once until they are exhausted, and you do it to extract all its content to the array, it's wrong to process it again in the while loop.
Besides that, to print to a filehandle you have to pass it as first argument to the print() function in the same call, and " " is not a newline, \n is a newline.
my #lines = <$in>;
#while (<$in>) {
for ( #lines ) {
print $out $_;
print $out "\n";
}
But you can forget all that code and learn the one-liners. This yields same result:
perl -ne 'print "$_\n"' input.txt >output.txt