How to log the file using Log::Log4perl module in perl - perl

I am beginner in perl .I write the script for adding two number using
Getopt::Long module .I am facing difficulty to log the below script using Log::Log4perl module. Can anyone please help me with that.
use strict;
use warnings;
use Getopt::Long;
use Log::Log4perl;
my $num1=<>;
my $num2=<>;
chomp($num1,$num2);
my $res=GetOptions("numone=i"=>\$num1,
"numtwo=i"=>\$num2);
my $add=$num1 + $num2;
print $add;

Here is an example:
use feature qw(say);
use strict;
use warnings;
use Getopt::Long;
use Log::Log4perl qw(:easy);
my $conf = do { local $/; <DATA> };
Log::Log4perl::init( \$conf );
my $num1;
my $num2;
if (#ARGV == 0) {
print "Enter number1: ";
chomp($num1 = <>);
INFO( "Read number1 from STDIN: '$num1'" );
print "Enter number2: ";
chomp($num2=<>);
INFO( "Read number2 from STDIN: '$num2'" );
}
else {
GetOptions("numone=i" =>\$num1, "numtwo=i"=>\$num2)
or die "Bad command line options\n";
die "Number1 undefined\n" if !defined $num1;
die "Number2 undefined\n" if !defined $num2;
INFO( "Read number1 from ARGV: '$num1'" );
INFO( "Read number2 from ARGV: '$num2'" );
}
my $add = $num1 + $num2;
say "Result: $num1 + $num2 = $add";
__DATA__
log4perl.rootLogger=INFO, LOGFILE
log4perl.appender.LOGFILE=Log::Log4perl::Appender::File
log4perl.appender.LOGFILE.filename=mylog.log
log4perl.appender.LOGFILE.mode=append
log4perl.appender.LOGFILE.layout=PatternLayout
log4perl.appender.LOGFILE.layout.ConversionPattern=[%r] %F %L %c - %m%n
Example session:
$ p.pl --numone=3 --numtwo=4
Result: 3 + 4 = 7
$ cat mylog.log
[0] ./p.pl 26 main - Read number1 from ARGV: '3'
[0] ./p.pl 27 main - Read number2 from ARGV: '4'

Related

How to split the digits to count the no of times it comes in perl

#! /usr/bin/perl
use strict;
use warnings;
my #array = ('0'..'9');
print "Enter the inp No's : ";
while (($inp = <STDIN>) cmp "\n"){
}
angus > perl no.pl
Enter the inp No's : 12123213123
I'm trying to find how many times each no comes and the total of all the digits.How to split each digit and find its occurence
You have not declared $inp. Also, your usage of cmp is weird, simple ne would work the same and would not confuse anyone.
You can split a string into characters by using an empty pattern in split and then count the numbers of occurrences in a hash:
#!/usr/bin/perl
use warnings;
use strict;
print "Enter the inp No's : ";
while ((my $inp = <STDIN>) ne "\n"){
my %digits;
$digits{$_}++ for split //, $inp;
for (0 .. 9) {
print "$_ ", $digits{$_} || 0, "\n";
}
}
The canonical way, though, is to use the tr operator. As it does not interpolate, we must use eval to get the variable value inside:
#!/usr/bin/perl
use warnings;
use strict;
print "Enter the inp No's : ";
my %digits;
while ((my $inp = <STDIN>) ne "\n"){
for (0 .. 9) {
my $n = eval "\$inp =~ tr/$_//";
print "$_ $n\n";
}
}

POSIX: strtod - question

Can someone explain me, how strtod works resp. why I get here 10,2 despite the en_EN-locale?
#!/usr/bin/env perl
use warnings;
use 5.012;
use POSIX qw(locale_h strtod);
setlocale( LC_NUMERIC, 'en_EN.UTF-8' );
my $str = '5,6';
$! = 0;
my ( $num, $n_unparsed ) = strtod( $str );
if ( $str eq '' or $n_unparsed != 0 or $! ) {
die "Non-numeric input $str" . $! ? ": $!\n" : "\n";
}
say $num + 4.6;
# 10,2
Your ISO 3166 identifier is wrong. Try US.

extract every nth number

i want to extract every 3rd number ( 42.034 , 41.630 , 40.158 as so on ) from the file
see example-
42.034 13.749 28.463 41.630 12.627 28.412 40.158 12.173 30.831 26.823
12.596 32.191 26.366 13.332 32.938 25.289 12.810 32.419 23.949 13.329
Any suggestions using perl script ?
Thanks,
dac
You can split file's contents to separate numbers and use the modulo operator to extract every 3rd number:
my $contents = do { local $/; open my $fh, "file" or die $!; <$fh> };
my #numbers = split /\s+/, $contents;
for (0..$#numbers) {
$_ % 3 == 0 and print "$numbers[$_]\n";
}
use strict;
use warnings;
use 5.010; ## for say
use List::MoreUtils qw/natatime/;
my #vals = qw/42.034 13.749 28.463 41.630 12.627 28.412 40.158 12.173 30.831
26.823 12.596 32.191 26.366 13.332 32.938 25.289 12.810 32.419 23.949 13.329/;
my $it = natatime 3, #vals;
say while (($_) = $it->());
This is probably the shortest way to specify that. If #list is your list of numbers
#list[ grep { $_ % 3 == 0 } 0..$#list ]
It's a one-liner!
$ perl -lane 'print for grep {++$i % 3 == 1} #F' /path/to/your/input
-n gives you line-by-line processing, -a autosplitting for field processing, and $i (effectively initialized to zero for our purposes) keeps count of the number of fields processed...
This method avoids reading the entire file into memory at once:
use strict;
my #queue;
while (<>) {
push #queue, / ( \d+ (?: \. \d* ) ? ) /gx;
while (#queue >= 3) {
my $third = (splice #queue, 0, 3)[2];
print $third, "\n"; # Or do whatever with it.
}
}
If the file has 10 numbers in every line you can use this:
perl -pe 's/([\d.]+) [\d.]+ [\d.]+/$1/g;' file
It's not a clean solution but it should "do the job".
Looks like this post lacked a solution that didn't read the whole file and used grep.
#!/usr/bin/perl -w
use strict;
my $re = qr/-?\d+(?:\.\d*)/; # Insert a more precise regexp here
my $n = 3;
my $count = 0;
while (<>) {
my #res = grep { not $count++ % $n } m/($re)/go;
print "#res\n";
};
I believe you’ll find that this work per spec, behaves politely, and never reads in more than it needs to.
#!/usr/bin/env perl
use 5.010_001;
use strict;
use autodie;
use warnings qw[ FATAL all ];
use open qw[ :std IO :utf8 ];
END { close STDOUT }
use Regexp::Common;
my $real_num_rx = $RE{num}{real};
my $left_edge_rx = qr{
(?: (?<= \A ) # or use \b
| (?<= \p{White_Space} ) # or use \D
)
}x;
my $right_edge_rx = qr{
(?= \z # or use \b
| \p{White_Space} # or use \D
)
}x;
my $a_number_rx = $left_edge_rx
. $real_num_rx
. $right_edge_rx
;
if (-t STDIN && #ARGV == 0) {
warn "$0: reading numbers from stdin,"
. " type ^D to end, ^C to kill\n";
}
$/ = " ";
my $count = 0;
while (<>) {
while (/($a_number_rx)/g) {
say $1 if $count++ % 3 == 0;
}
}

How to write from n-th row to a file using perl

I have a source text in a file and looking for a code that would take the second (or n-th - in general) row from this file and print to a seperate file.
Any idea how to do this?
You can do this natively in Perl with the flip-flop operator and the special variable $. (used internally by ..), which contains the current line number:
# prints lines 3 to 8 inclusive from stdin:
while (<>)
{
print if 3 .. 8;
}
Or from the command line:
perl -wne'print if 3 .. 8' < filename.txt >> output.txt
You can also do this without Perl with: head -n3 filename.txt | tail -n1 >> output.txt
You could always:
Read all of the file in and but it into one variable.
Split the variable at the newline and store in an array
Write the value at the index 1 (for the second row) or the n-1 position to the separate file
use like this script.pl > outfile (or >> outfile for append)
this uses lexical filehandles and 3 arg open which are preferred to global filehandles and 2 arg open.
#!/usr/bin/perl
use strict;
use warnings;
use English qw( -no_match_vars );
use Carp qw( croak );
my ( $fn, $line_num ) = #ARGV;
open ( my $in_fh, '<', "$fn" ) or croak "Can't open '$fn': $OS_ERROR";
while ( my $line = <$in_fh> ) {
if ( $INPUT_LINE_NUMBER == $line_num ) {
print "$line";
}
}
note: $INPUT_LINE_NUMBER == $.
here's a slightly improved version that handles arbitrary amounts of line numbers and prints to a file.
script.pl <infile> <outfile> <num1> <num2> <num3> ...
#!/usr/bin/perl
use strict;
use warnings;
use English qw( -no_match_vars );
use Carp qw( croak );
use List::MoreUtils qw( any );
my ( $ifn, $ofn, #line_nums ) = #ARGV;
open ( my $in_fh , '<', "$ifn" ) or croak "can't open '$ifn': $OS_ERROR";
open ( my $out_fh, '>', "$ofn" ) or croak "can't open '$ofn': $OS_ERROR";
while ( my $line = <$in_fh> ) {
if ( any { $INPUT_LINE_NUMBER eq $_ } #line_nums ) {
print { $out_fh } "$line";
}
}
I think this will do what you want:
line_transfer_script.pl:
open(READFILE, "<file_to_read_from.txt");
open(WRITEFILE, ">File_to_write_to.txt");
my $line_to_print = $ARGV[0]; // you can set this to whatever you want, just pass the line you want transferred in as the first argument to the script
my $current_line_counter = 0;
while( my $current_line = <READFILE> ) {
if( $current_line_counter == $line_to_print ) {
print WRITEFILE $current_line;
}
$current_line_counter++;
}
close(WRITEFILE);
close(READFILE);
Then you'd call it like: perl line_transfer_script.pl 2 and that would write the 2nd line from file_to_read_from.txt into file_to_write_to.txt.
my $content = `tail -n +$line $input`;
open OUTPUT, ">$output" or die $!;
print OUTPUT $content;
close OUTPUT;

How can I write a Perl script that generates a new log file each time it's run?

I am trying to modify a Perl script to create a different/new log file each time I run the script. I was trying to create each log file by date, but I am having trouble incorporating this concept... This is what I have so far:
#!perl -w
use WWW::Mechanize;
# What URL shall we retrieve?
$url = "http://www.mediabase.com/whatsong/whatsong.asp?var_s=075068071069045070077";
# Create a new instance of WWW::Mechanize
# enabling autocheck checks each request to ensure it was successful,
# producing an error if not.
my $mechanize = WWW::Mechanize->new(autocheck => 1);
# Retrieve the page
$mechanize->get($url);
# Assign the page content to $page
my $page = $mechanize->content;
# Output the page
#print $page;
# Let's also save the page locally
open LOG, ">>", "102.1_content.txt";
#print LOG $page; #######get error here when run from c++....
close(LOG);
########################################
########################################
# INPUT_FILE
open INPUT_FILE, "<", "102.1_content.txt";
########################################
my $html = join '', <INPUT_FILE>;
my #stuff = $html =~ />([^<]+)</g;
########################################
use Time::localtime;
$tm = localtime;
print "*****", $tm->mon+1, "/", $tm->mday, "/",
$tm->year+1900, "--", $tm->hour, "::",
$tm->min, "::", $tm->sec,
"******************************";
##sec, min, hour, mday, mon, year, wday, yday, and isdst
########################################
# OUTPUT_FILE
open OUTPUT_FILE, ">>", ("PLAYLIST_TABLE_"$tm->mon+1, "/", $tm->mday, "/", tm->year+1900".txt") or die $!;
########################################
print OUTPUT_FILE "******************************",
$tm->mon+1, "/", $tm->mday, "/", $tm->year+1900,
"--", $tm->hour, "::", $tm->min, "::", $tm->sec,
"******************************");
print join (" ", #stuff), "\n";
print OUTPUT_FILE join (" ", #stuff), "\n";
print "thats all!\n";
close(INPUT_FILE);
close(OUTPUT_FILE);
I apologize, I know my code is messy, and thanks in advance...
Nick
Use File::Spec or Path::Class to manipulate file names and paths:
#!/usr/bin/perl
use strict;
use warnings;
use File::Spec::Functions qw( catfile );
my ($mday, $mon, $year) = (localtime)[3 .. 5];
my $filename = catfile(
sprintf('PLAYLIST_TABLE_%02d', $mon + 1),
sprintf('%02d', $mday),
sprintf('%04d.txt', $year + 1900)
);
print $filename, "\n";
Output (on Windows):
PLAYLIST_TABLE_11\06\2009.txt
However, I would recommend you use:
my $filename = catfile(
sprintf('%04d.txt', $year + 1900)
sprintf('PLAYLIST_TABLE_%02d', $mon + 1),
sprintf('%02d', $mday),
);
so log files from runs close in time remain 'close' in the file system.
Please avoid having really long lines of string concatenations. They make it really hard to see what is going on an hide syntax errors in clutter. Instead, you could use join:
join('/',
"PLAYLIST_TABLE_" . ($tm->mon + 1),
$tm->mday,
($tm->year + 1900) . '.txt'
);
You should use . (dot) to concatenate strings. Here for the filename string it becomes :
open (OUTPUT_FILE, ">> PLAYLIST_TABLE_" . ($tm->mon+1) . "/" . $tm->mday . "/" . ($tm->year+1900) . ".txt") or die $!;
The , (comma) works only with print AFAIK, and only because the usual transformation of an array in string is concatenation for print.
You're forgetting to do error checking, so
use autodie;
We should all prefer a ISO8601 formatted date/time stamp :)
#!/usr/bin/perl --
use strict;
use warnings;
use File::Spec;
use POSIX();
my $thisf = File::Spec->rel2abs(__FILE__);
my $thisl = sprintf '%s-log-%s.txt', $thisf, POSIX::strftime(q!%Y-%m-%d-%H.%M.%SZ!,gmtime);
print "
thisf $thisf
thisl $thisl
";
__END__
$ perl tmp.pl
thisf /home/boy/tmp.pl
thisl /home/boy/tmp.pl-log-2009-11-08-20.35.38Z.txt
$