unable to write the output into a file in perl - perl

I want to write the result of my code into a file , but it's not written into my file. My code is working and it's about removing duplicate line, but when i wanted to write the output into a file, the file is empty. This is my code:
use strict;
use warnings;
open(DATA,"/root/Desktop/SIEMENS/printtokens/outputs/common_distinct/MR1/thiscommon.txt");
open FILE2, ">/root/Desktop/SIEMENS/printtokens/outputs/common_distinct/MR1/common_element.txt" or die $!;
my %lines;
#open DATA, $ARGV[0] or die "Couldn't open $ARGV[0]: $!\n";
while (<DATA>) {
print if not $lines{$_}++;
print FILE2 if not $lines{$_}++;
}
close DATA;
close FILE2;

This works as expected
use strict;
use warnings;
use autodie;
open(my $in, '<', './in.txt');
open(my $out, '>', './out.txt');
my %lines;
while (<$in>) {
print $out $_ unless $lines{$_}++;
}
close $in;
close $out;
Note the usage of the 3-argument open, lexical filehandles and the autodie pragma.
Me as a fan of the usage of CPAN modules, would write the same as:
use 5.014;
use warnings;
use Path::Tiny;
use List::Util qw(uniq);
my $out_file = './out.txt';
my $in_file = './in.txt';
path($out_file)->spew( uniq path($in_file)->lines );

Your main problem probably is that $lines{$_}++ changes the value of $lines{$_} so the second will never evaluate to false. You could probably fix your problem just by removing ++ on the first occurence. But for readability I would recommend wrapping both output lines with one if statement, avoid using $_ and remembering to close the files, so something like:
use strict;
use warnings;
my %lines;
open(my $in, '<', './in.txt');
open(my $out, '>', './out.txt');
while (my $line = <$in>) {
unless ($lines{$line}++) {
print STDOUT $line;
print {$out} $line
}
}
close($in);
close($out);
As you can see, I also prefer lexical filehandles and 3-argument open.

Not quite sure what you want in common_element.txt, but I think the logic in the read loop is wrong. No need to increase the $lines twice, and only output if there is a match from existing data?
Try:
use strict;
use warnings;
open(DATA,"thiscommon.txt");
open (FILE2, '>common_element.txt') or die $!;
my %lines;
while (<DATA>) {
print FILE2 if $lines{$_};
print if not $lines{$_}++;
}
close DATA;
close FILE2;
Only with your paths, obviously.

Related

Extract private key and write to a new file in perl

Simply put, I want to extract the entire private key, listed below, from trust.pem and save that text to a new file (tmp6.pem), using Perl. My current implementation only gives me the first for letters of the key.
-----BEGIN CERTIFICATE-----
MIIDazCCAtSgAwIBAgIBCDANBgkqhkiG9w0BAQQFADA8MQ8wDQYDVQQDEwZoMjFk
Y2ExDTALBgNVBAsTBFdJTlQxDTALBgNVBAoTBFdJTlQxCzAJBgNVBAYTAlVTMB4X
DTE1MDQxNjA0MTYyNloXDTI1MDQxMzA0MTYyNlowQjELMAkGA1UEBhMCVVMxDTAL
BgNVBAoTBFdJTlQxDTALBgNVBAsTBFdJTlQxFTATBgNVBAMTDGgyMWRjYS1vY3Nw
NDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCVRB8NpRhOZIpPk2qb
xqPS/X6odDsGVxHofnLJBRLBjOPQgUpa9FsXZ5//ZMMSSpudRN5N0eIcnAzPED78
FgLWbAm+D0j+OsE+1DLr+qwputxhz2Fm7f6snb/MH3JqGpioyREkY8yxNHDrN7nP
hp2fpZojlaow/Bpxg9iPZZm+J8C9NY9vun7/vLx3O5BOdH0A/qWlo4qmxH0d1vTi
KTGNE9hKE2Fl1KtZhsrJRKgOu6B0ATYL75NPKANOzNKLZmxlF2HKd3FIEOAEzSFS
/ZaJHwPD4SyLapFwqxMVfDF+MPb2Tvs9YEHBraNxWx8OiB27nAss1zfF7JeKnpck
ApsCAwEAAaOB8jCB7zAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM
IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUY+cf2lJ6EZhgAy/rQU8f
Z4FGNLcwZgYDVR0jBF8wXYAU2Q1ss1/VO6fejshKp0XizESFEB6hQqRAMD4xETAP
BgNVBAMTCHdpbnRyb290MQ0wCwYDVQQLEwRXSU5UMQ0wCwYDVQQKEwRXSU5UMQsw
CQYDVQQGEwJVU4IBDzALBgNVHQ8EBAMCBeAwIAYDVR0lAQH/BBYwFAYIKwYBBQUH
AwEGCCsGAQUFBwMJMA0GCSqGSIb3DQEBBAUAA4GBAEETJk/Jt0/JNpKjhU6QbYhy
UNErAJyclyrrbC4JyKbTABzLyubYZz2g0VM+YKHmhHliGosjx4yqKqUc44zvYqzW
o0EpuOWDTnj7yXUZjDozVDSJiZcr27I2R3aOxvF4PGw2bk/sWRcs7QMhgT2z5RRE
vXIYrGIjW2jFz1oKHGGT
-----END CERTIFICATE-----
Here is my code, thus far:
use warnings;
use strict;
use FileHandle;
use Fcntl qw(:DEFAULT :flock :seek); # import LOCK_* constants
my $F_IN = FileHandle->new("<trust.pem");
my $F_OUT = FileHandle->new(">tmp6.pem");
while (my $line = $F_IN->getline) {
if ($line =~ m|(MIID)|) {
$F_OUT->print("$1\n");
}
}
$F_IN->close();
$F_OUT->close();
This will skip the first and last lines of the input file by using the input line number to detect the first line and checking whether the next read would return end of file to detect the last line:
use strict;
use warnings;
open(my $in, '<', 'trust.pem') or die $!;
open(my $out, '>', 'tmp6.pem') or die $!;
while (<$in>) {
next if $. == 1;
last if eof($in);
print $out $_;
}
close($in);
close($out);
If you don't mind reading the entire file into memory---which is no problem at all in this case---you could use shift and pop to remove the first and last lines from the array:
use strict;
use warnings;
open(my $in, '<', 'trust.pem') or die $!;
my #lines = <$in>;
close($in);
shift(#lines);
pop(#lines);
open(my $out, '>', 'tmp6.pem') or die $!;
print $out #lines;
close($out);
Note that the previous examples won't work very well if you have any leading or trailing blank lines. In that case, I'd probably do something like this instead, which skips PEM file headers/footers and lines containing only whitespace:
use strict;
use warnings;
open(my $in, '<', 'trust.pem') or die $!;
open(my $out, '>', 'tmp6.pem') or die $!;
while (<$in>) {
next unless /\S/;
next if /^-----/;
print $out $_;
}
close($in);
close($out);

How to replace ^M character in perl code in same file

I am looking to delete control-M character file in perl code (not perl one liner).
I tried this, but it will write to new file. Whats the way to do it in same file?
#!/usr/bin/perl
open (IN, '<', "FILE.dat") or die "$!";
open (OUT, '>', "FILE.dat.cpy") or die "$!";
while(<IN>)
{
$line = $_;
$line=~ tr/\015//d;
print OUT "$line";
}
close (IN);
close (OUT);
store the file internal in a String.
#!/usr/bin/perl
my $content = ''
open (IN, '<', "FILE.dat") or die "$!";
while(<IN>)
{
$line = $_;
$line=~ tr/\015//d;
$content .$line
}
close (IN);
open (OUT, '>', "FILE.dat") or die "$!";
print OUT $line;
close (OUT);
It could be done using $^I variable.
use autodie;
local $^I = "";
local #ARGV = "FILE.dat";
while (my $line = <>) {
$line=~ tr/\r//d;
print $line;
}
From perlvar
$^I - The current value of the inplace-edit extension. Use undef to disable inplace editing.
So it is undef by default, empty string is used to edit in-place, and non-empty string will be added as suffix to backup file name.
You needn't be afraid of coping the edited content to a new file, and then renaming. This is the standard way to edit content unless you're dealing with a file with fixed with records.
Check out How do I change, delete, or insert a line in a file, or append to the beginning of a file? to observe most of the ways to edit content, and the majority of them will ultimately be copying to a new file.
My preferred advice is to use in-place edit as demonstrated by mpapec. The only addition is that Windows forces you to specify a backup, so just need to add the unlink line after the processing.
use strict;
use warnings;
use autodie;
my $file = 'FILE.dat';
local #ARGV = $file;
local $^I = '.bak';
while (<>) {
tr/\r//d;
print;
}
unlink "$file$^I";
If you insist on being able to open the file only once, then perhaps you can take a look at I still don't get locking. I just want to increment the number in the file. How can I do this?
use strict;
use warnings;
use autodie;
use Fcntl qw(:seek);
my $file = 'afile.dat';
open my $fh, '+<:raw', $file;
my $data = do {local $/; <$fh>};
seek $fh, SEEK_SET, 0;
truncate $fh, 0;
$data =~ tr/\r//d;
print $fh $data;
close $fh;

redirection of the result in a file text

I do a perl scrip that it creates a hash directly from the contents of the first file, and then reads each line of the second, checks the hash to see if it should be printed.
Here is the perl script :
use strict;
use warnings;
use autodie;
my %permitted = do {
open my $fh, '<', 'f1.txt';
map { /(.+?)\s+\(/, 1 } <$fh>;
};
open my $fh, '<', 'f2.txt';
while (<$fh>) {
my ($phrase) = /(.+?)\s+->/;
print if $permitted{$phrase};
}
I am looking for how i print the result in a file text because this script actually print the result on the screen.
Thank you in advance.
Cordially
$ perl thescript.pl > result.txt
Will run your script and put the printed output in result.txt
Or, from within the script itself:
use strict;
use warnings;
use autodie;
my %permitted = do {
open my $fh, '<', 'f1.txt';
map { /(.+?)\s+\(/, 1 } <$fh>;
};
# Open result.txt for writing:
open my $out_fh, '>', 'result.txt' or die "open: $!";
open my $fh, '<', 'f2.txt';
while (<$fh>) {
my ($phrase) = /(.+?)\s+->/;
# print output to result.txt
print $out_fh $_ if $permitted{$phrase};
}
Open a new filehandle in write mode, then print to it. See perldoc -f print or http://perldoc.perl.org/functions/print.html for more info
...
open my $fh, '<', 'f2.txt';
open my $out_fh, '>', 'output.txt';
while (<$fh>) {
my ($phrase) = /(.+?)\s+->/;
print $out_fh $_
if $permitted{$phrase};
}
mapping the file contents first produces a list of all of the file's lines. This isn't necessarily a bad thing, unless the file's substantially large. grebneke showed how to direct output to a file, using > result.txt. Given this, and the (possible) map issue, consider just passing both files to the script from the command line, and process them using whiles:
use strict;
use warnings;
my %permitted;
while (<>) {
$permitted{$1} = 1 if /(.+?)\s+\(/;
last if eof;
}
while (<>) {
print if /(.+?)\s+->/ and $permitted{$1};
}
Usage: perl script.pl f1.txt f2.txt > result.txt
Hope this helps!

Writing results in a text file with perl

I have a problem when the script print the whole line of text file in a result text file:
use strict;
use warnings;
use autodie;
my $out = "result2.txt";
open my $outFile, ">$out" or die $!;
my %permitted = do {
open my $fh, '<', 'f1.txt';
map { /(.+?)\s+\(/, 1 } <$fh>;
};
open my $fh, '<', 'f2.txt';
while (<$fh>) {
my ($phrase) = /(.+?)\s+->/;
if ($permitted{$phrase}) {
print $outFile $fh;
}
close $outFile;
The problem is in this line
print $outFile $fh;
Any idea please?
Thank you
print $outFile $fh is printing the value of the file handle $fh to the file handle $outFile. Instead you want to print the entire current line, which is in $_.
There are a couple of other improvements that can be made
You should always use the three-parameter form of open, so the open mode appears on its own as the second paremeter
There is no need to test the success of an open of autodie is in place
If you have a variable that contains the name of the output file, then you really should have ones for the names of the two input files as well
This is how your program should look. I hope it helps.
use strict;
use warnings;
use autodie;
my ($in1, $in2, $out) = qw/ f1.txt f2.txt result2.txt /;
my %permitted = do {
open my $fh, '<', $in1;
map { /(.+?)\s+\(/, 1 } <$fh>;
};
open my $fh, '<', $in2;
open my $outfh, '>', $out;
while (<$fh>) {
my ($phrase) = /(.+?)\s+->/;
if ($permitted{$phrase}) {
print $outfh $_;
}
}
close $outfh;
I think you want print $outfile $phrase here, don't you? The line you currently have is trying to print out a file handle reference ($fh) to a file ($outfile).
Also, just as part of perl best practices, you'll want to use the three argument open for your first open line:
open my $outFile, ">", $out or die $!;
(FWIW, you're already using 3-arg open for your other two calls to open.)
Although Borodin has provided an excellent solution to your question, here's another option where you pass your 'in' files' names to the script on the command line, and let Perl handle the opening and closing of those files:
use strict;
use warnings;
my $file2 = pop;
my %permitted = map { /(.+?)\s+\(/, 1 } <>;
push #ARGV, $file2;
while (<>) {
my ($phrase) = /(.+?)\s+->/;
print if $permitted{$phrase};
}
Usage: perl script.pl inFile1 inFile2 [>outFile]
The last, optional parameter directs output to a file.
The pop command implicitly removes inFile2's name off of #ARGV, and stores it in $file2. Then, inFile1 is read using the <> directive. The file name of inFile2 is then pushed onto #ARGV, and that file is read and a line is printed if $permitted{$phrase} is true.
Running the script without the last, optional parameter will print results (if any) to the screen. Using the last parameter saves output to a file.
Hope this helps!

error : Name "main::outFile" used only once

I a problem with my perl script:
use strict;
use warnings;
use autodie;
my $out = "result2.txt";
open outFile, ">$out" or die $!;
my %permitted = do {
open my $fh, '<', 'f1.txt';
map { /(.+?)\s+\(/, 1 } <$fh>;
};
open my $fh, '<', 'f2.txt';
while (<$fh>) {
my ($phrase) = /(.+?)\s+->/;
if ($permitted{$phrase}) { print outFile $phrase ;}
}
close outFile;
The error is :
Name "main::outFile" used only once: possible typo at teeest.pl line 14.
Any idea please?
thank you
print has a very special syntax. Without use autodie,
print outFile $phrase;
means
print *outFile $phrase;
But the print replacement use autodie; creates can't quite reproduce that. It probably ends up being
print "outFile" $phrase;
which still does the right thing, but hides the use of outFile from the "used only once" warning checker.
The warning is spurious and harmless in this case. You can prevent it from being emitted by avoiding the unwarranted use of a global variable.
open my $outFile, ">$out" or die $!;
print $outFile $phrase;
close $outFile;