Extract private key and write to a new file in perl - 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);

Related

Read a text file and store each line in a variable using perl

I have a text file (sample.txt) with some data. I want to read the text file and store each line in an array or a variable.
sample.txt
ab1234
str:abcd
pq4567
How can i store each of these lines in an array or a variable using perl script.
It is easy. We open the file, push each line in the file to an array after you chomped \n (newline characters) and to test it, we print the array.
Here $_ is each of the lines read from file where #lines will store each of $_ in an array.
use strict;
use warnings
my $file = "sample.txt";
open(my $fh, "<", "sample.txt") or die "Unable to open < sample.txt: $!";
my #lines;
while (<$fh>) {
chomp $_;
push (#lines, $_);
}
close $fh or die "Unable to open $file: $!";
print #lines;
an even easier method is to just store the content to array.
use strict;
use warnings
my $file = "sample.txt";
open(my $fh, "<", "sample.txt") or die "Unable to open < sample.txt: $!";
my #lines = <$fh>;
chomp(#lines);
print #lines;
# open the file
open my $fh, '<', 'sample.txt'
or die "Could not open sample.txt: $!";
# Read the file into an array
my #lines = <$fh>;
# Optionally, remove newlines from all lines in the array
chomp(#lines);
If you are able to use CPAN modules, then Tie::File is there for your help.
Using this module you can modify, add or delete the contents in the file.
below is the script.
#!/usr/bin/perl
use strict;
use warnings;
use Tie::File;
my #contents=();
tie #contents, 'Tie::File','sample.txt' or die "Not able to Tie sample.txt\n";
my $count=1;
foreach (#contents)
{
print "line $count:$_\n";
$count++;
}
untie #contents;
output:
line 1: ab1234
line 2: str:abcd
line 3: pq4567

unable to write the output into a file in 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.

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;

Perl: Skip line N while reading a file

How would I skip say line 9 while I'm parsing a text file?
Here's what I got
use strict; use warnings;
open(my $fh, '<', 'file.txt') or die $!;
my $skip = 1;
while (<$fh>){
$_=~ s/\r//;
chomp;
next if ($skip eq 9)
$skip++;
}
Not sure if this works but I'm sure there's a more eloquent of doing it.
You can use $.:
use strict; use warnings;
open(my $fh, '<', 'file.txt') or die $!;
while (<$fh>){
next if $. == 9;
$_=~ s/\r//;
chomp;
# process line
}
Can also use $fh->input_line_number()

Read Increment Then Write to a text file in perl

I have this little perl script which opens a txt file, reads the number in it, then overwrites the file with the number incremented by 1. I can open and read from the file, I can write to the file but I"m having issues overwriting. In addition, I'm wondering if there is a way to do this without opening the file twice. Here's my code:
#!/usr/bin/perl
open (FILE, "<", "data.txt") or die "$! error trying to a\
ppend";
undef $/;
$number = <FILE>;
$number = int($number);
$myNumber = $number++;
print $myNumber+'\n';
close(FILE);
open(FILE, ">data.txt") or die "$! error";
print FILE $myNumber;
close(FILE);
Change the line
$myNumber = $number++;
to
$myNumber = $number+1;
That should solve the problem.
Below is how you could do by opening the file just once:
open(FILE, "+<data.txt") or die "$! error";
undef $/;
$number = <FILE>;
$number = int($number);
$myNumber = $number+1;
seek(FILE, 0, 0);
truncate(FILE, tell FILE);
print $myNumber+"\n";
print FILE $myNumber;
close(FILE);
It's good that you used the three-argument form of open the first time. You also needed to do that in your second open. Also, you should use lexical variables, i.e., those which begin with my, in your script--even for your file handles.
You can just increment the variable that holds the number, instead of passing it to a new variable. Also, it's a good idea to use chomp. This things being said, consider the following option:
#!/usr/bin/env perl
use strict;
use warnings;
undef $/;
open my $fhIN, "<", "data.txt" or die "Error trying to open for reading: $!";
chomp( my $number = <$fhIN> );
close $fhIN;
$number++;
open my $fhOUT, ">", "data.txt" or die "Error trying to open for writing: $!";
print $fhOUT $number;
close $fhOUT;
Another option is to use the Module File::Slurp, letting it handle all the I/O operations:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Slurp qw/edit_file/;
edit_file { chomp; $_++ } 'data.txt';
Try this:
#!/usr/bin/perl
use strict;
use warnings;
my $file = "data.txt";
my $number = 0;
my $fh;
if( -e $file ) {
open $fh, "+<", $file or die "Opening '$file' failed, because $!\n";
$number = <$fh>;
seek( $fh, 0, 0 );
} else { # if no data.txt exists - yet
open $fh, ">", $file or die "Creating '$file' failed, because $!\n";
}
$number++;
print "$number\n";
print $fh $number;
close( $fh );
If you're using a bash shell, and you save the code to test.pl, you can test it with:
for i in {1..10}; do ./test.pl; done
Then 'cat data.txt', should show a 10.