Why isn't my Perl format working? - perl

All,
I'm trying to get the code at the bottom to look like a check. Could you help me troubleshoot?
Thanks,
Frank
format STDOUT =
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
$chkno $chkno
$first $last
$addr[0]
$addr[1]
$phone $date
Pay to the
Order of: $payee $amount
For: $memo Stamped Signature
nova> perl proj3_3.pl
Use of comma-less variable list is deprecated at proj3_3.pl line 48.
Name "main::date" used only once: possible typo at proj3_3.pl line 24.
Name "main::last" used only once: possible typo at proj3_3.pl line 12.
Name "main::payee" used only once: possible typo at proj3_3.pl line 27.
Name "main::phone" used only once: possible typo at proj3_3.pl line 21.
Name "main::amount" used only once: possible typo at proj3_3.pl line 30.
Name "main::first" used only once: possible typo at proj3_3.pl line 9.
Name "main::memo" used only once: possible typo at proj3_3.pl line 33.
What is your Check Number? asdf
What is your First Name? asdf
What is your Last Name? adsf
What is your street address (i.e. 555 Anywhere St.)? asdf
What is your city, state, zip code (i.e. Los Angeles, CA, 90210)? as
What is your Phone Number? df
What is the Date? asdf
Who is the Payee? asd
What is the Check Amount? fa
What is the Check's Purpose (MEMO)? sdf
asdf asdf
$first $last
$addr[0]
$addr[1]
$phone $date
Pay to the
Order of: $payee $amount
For: $memo Stamped Signature
.
format STDOUT_TOP =
--------------------------------------------------------------
Edit... Sorry, new to this. Here's my code:
#!/usr/bin/perl -w
use FileHandle
print "What is your Check Number? ";
chomp($chkno = <STDIN>);
print "What is your First Name? ";
chomp($first = <STDIN>);
print "What is your Last Name? ";
chomp($last = <STDIN>);
print "What is your street address (i.e. 555 Anywhere St.)? ";
chomp($addr[0] = <STDIN>);
print "What is your city, state, zip code (i.e. Los Angeles, CA, 90210)? ";
chomp($addr[1] = <STDIN>);
print "What is your Phone Number? ";
chomp($phone = <STDIN>);
print "What is the Date? ";
chomp($date = <STDIN>);
print "Who is the Payee? ";
chomp($payee = <STDIN>);
print "What is the Check Amount? ";
chomp($amount = <STDIN>);
print "What is the Check's Purpose (MEMO)? ";
chomp($memo = <STDIN>);
#print "? ";
#chomp($ = <STDIN>);
#print "? ";
#chomp($ = <STDIN>);
# #>>>> right-justified
# #|||| centered
# #####.## numeric field holder
# #* multiline field holder
# now this line format will automatically apply to CHECK
format STDOUT =
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
$chkno $chkno
$first $last
$addr[0]
$addr[1]
$phone $date
Pay to the
Order of: $payee $amount
For: $memo Stamped Signature
.
# and this page header format will automatically apply to CHECK
format STDOUT_TOP =
--------------------------------------------------------------
.
write STDOUT; #send to the output

Formats consist of a format line followed by the variables that go in that line (comma separated):
#!/usr/bin/perl
use strict;
use warnings;
our $first = "Chas.";
our $last = "Owens";
our $chkno = "123456";
our #addr = ("123 Nowhere Lane", "Citysville, Townshire, 12345");
our $phone = "123-456-7890";
our $date = "2009-08-10";
our $payee = "Stack Overflow";
our $amount = "0.02";
our $amount_str = "no dollars and two cents";
our $memo = "my two cents worth";
write;
format STDOUT =
#<<<<<<<<<<<<< #<<<<<<<<<<<<<<<< #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
$first, $last, $chkno
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$addr[0]
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Date:
$addr[1]
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #<<<<<<<<<<<<<<<<<<<<<<<
$phone, $date
Pay to the
Order of: #<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ########.##
$payee, $amount
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< dollars
$amount_str
Signature
Memo: #<<<<<<<<<<<<<<<<<<<<<<<<<<< _________________________
$memo
.
That said, formats have some really bad drawbacks and you should really use a different solution. Another option is to use Perl6::Form. It is a backport of the draft of formats for Perl 6:
#!/usr/bin/perl
use strict;
use warnings;
use Perl6::Form;
my $first = "Chas.";
my $last = "Owens";
my $chkno = "123456";
my #addr = ("123 Nowhere Lane", "Citysville, Townshire, 12345");
my $phone = "123-456-7890";
my $date = "2009-08-10";
my $payee = "Stack Overflow";
my $amount = "0.02";
my $amount_str = "no dollars and two cents";
my $memo = "my two cents worth";
print form
"{<<<<<<<<<<<<<} {<<<<<<<<<<<<<<<<} {>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}",
$first, $last, $chkno,
"{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<}",
$addr[0],
"{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<} Date:",
$addr[1],
"{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<} {<<<<<<<<<<<<<<<<<<<<<<<}",
$phone, $date,
"",
"Pay to the",
'Order of: {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<} ${>>>>>>>.<<}',
$payee, $amount,
"{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<} dollars",
$amount_str,
" Signature",
"Memo: {<<<<<<<<<<<<<<<<<<<<<<<<<<<} _________________________",
$memo;

Related

Harvesting repository // "From=>" and "Until=>" with user input variable

I am using „from=>“ and “until=>” while harvesting a repository with OAI-PMH written in Perl. I tried to let the user type in start- and end-date with <STDIN> in format yyyy-mm-dd. But instead of giving me back the records/results the compiler seems to ignore my query / request, at least it does not give me any results. I have enclosed the relevant parts of the code below. Thanks for your help!
#! /usr/bin/perl
use warnings;
use strict;
use Net::OAI::Harvester;
use Time::Piece;
use Time::Seconds;
my $harvester = Net::OAI::Harvester->new(
baseURL => 'https://opus4.XXX/oai'
);
my $weekAgo = localtime() - ONE_WEEK;
$weekAgo = $weekAgo->ymd;
my $monthAgo = localtime() - ONE_MONTH;
$monthAgo = $monthAgo->ymd;
print "Please enter a number \n
1 for last weeks records \n
2 for last months records \n
3 for records from ... until ...\n";
my $input = <STDIN>;
[...]
elsif( $input == 3 ) {
print "enter start date (yyyy-mm-dd): ";
my $from = <STDIN>;
print "Enter final date (yyyy-mm-dd): ";
my $until = <STDIN>;
my $list = $harvester->listRecords(
metadataPrefix => 'oai_dc',
from=>$from,
until=>$until
);
search($list);
}
sub search {
my $list = $_[0];
while ( my $record = $list->next ) {
my $datestamp = $record->header->datestamp;
print "[ time stamp: ",$datestamp," ]","\n";
my $metadata = $record->metadata;
print "Title: ",$metadata->title,"\n";
[...]}
}
Changed answer due to feedback
Try chomping your input. It may confuse the module you are passing the values to. E.g. change
my $from = <STDIN>;
to
chomp(my $from = <STDIN>);

Need help understanding this Perl snippet

I'm reading Learning Perl (6th edition) and came upon a code snippet that I couldn't decipher. One of the exercises after chapter 14 asks to build a program that takes as input a string and a substring then finds the indices at which the substring occurs in the string.
Here's the way I did it:
print "Enter a string: ";
chomp($string = <STDIN>);
print "Enter a substring: ";
chomp($sub = <STDIN>);
until ($index == -1) {
print $index, "\n" if defined($index);
$index = index($string, $sub, $index + 1);
}
In the answers section, they show two ways. One is easy to understand and similar to mine, but the other is purposefully obfuscating:
print "Enter a string: ";
chomp($string = <STDIN>);
print "Enter a substring: ";
chomp($sub = <STDIN>);
for (my $pos = –1; –1 !=
($pos = index
+$string,
+$sub,
+$pos
+1
);
push #places, ((((+$pos))))) {
'for ($pos != 1; # ;$pos++) {
print "position $pos\n";#;';#' } pop #places;
}
print "Locations of '$sub' in '$string' were: #places\n";
I have almost no idea what's going on in that for loop. I know it's of the form for (initialize; test; increment) and that it's testing that the index is not -1, which means no more occurrences of the substring. But what's going on with the assignment to $pos? Why are there so many parentheses around +$pos? What's going on after the many parentheses? I'd really appreciate it if someone could walk me through the second part. Please keep in mind I've just started learning Perl a week ago.
BTW, I tried running their code but it gave me this error:
Unrecognized character \xE2; marked by <-- HERE after my $pos = <-- HERE near column 16 at ex14.obfs.pl line 1.
I've simplified your example just a little bit, discarded the useless junk and comments. Hope now it is clear what's going on:
print "Please enter a string: ";
chomp(my $string = <STDIN>);
print "Please enter a substring: ";
chomp(my $sub = <STDIN>);
my #places;
for (my $pos = -1; -1 != ($pos = index $string, $sub, $pos+1); push #places, $pos)
{
#do nothing here
}
print "Locations of '$sub' in '$string' were: #places\n";
The compilation error was due to '–' instead of '-';
The inner loop was in fact a string literal (useless) plus comments (useless), the extra braces are useless as well.

PERL Fixed Width to CSV based on Input Files

EDITED: I'm attempting to create a brief script that calls for an input fixed width file and a file with the start position and length of each attribute and then outputs the file as CSV instead of fixed width. I haven't messed with removing whitespace yet and am currently focusing on building the file reader portion.
Fixed:
My current issue is that this code returns data from the third row for $StartPosition and from the fourth row for $Length when they should both be first found on the first row of COMMA. I have no idea what is prompting this behavior.
Next issue: It only reads the first record in practice_data.txt I'm guessing it's something where I need to tell COMMA to go back to the beginning?
while (my $sourceLine = <SOURCE>) {
$StartPosition = 0;
$Length = 0;
$Output = "";
$NextRecord ="";
while (my $commaLine = <COMMA>) {
my $Comma = index($commaLine, ',');
print "Comma location found at $Comma \n";
$StartPosition = substr($commaLine, 0, $Comma);
print "Start position is $StartPosition \n";
$Comma = $Comma + 1
$Length = substr($commaLine, $Comma);
print "Length is $Length \n";
$NextRecord = substr($sourceLine, $StartPosition, $Length);
$Output = "$Output . ',' . $NextRecord";
}
print OUTPUT "$Output \n";
}
practice_data.txt
1234512345John Doe 123 Mulberry Lane Columbus Ohio 43215Johnny Jane
5432154321Jason McKinny 423 Thursday Lane Columbus Ohio 43212Jase Jamie
4321543212Mike Jameson 289 Front Street Cleveland Ohio 43623James Sarah
Each record is 100 characters long.
Definitions.txt:
0,10
10,10
20,10
30,20
50,10
60,10
70,5
75,15
90,10
It always helps to provide enough information so that we can at least do some testing without having to read your code and imagine what the data must look like.
I suggest you use unpack, after first building a template from the file that holds the field specifications. Note that the A field specifier trims trailing spaces from the data.
It is all but essential to use the Text::CSV module to parse or generate well-formed CSV data. And I have used the autodie pragma to avoid having to explicitly check and report on the status of every I/O operation.
I have used this data
my_source_data.txt
12345678 ABCDE1234FGHIJK
my_field_spec.txt
0,8
10,5
15,4
19,6
And this program
use strict;
use warnings;
use 5.010;
use autodie;
use Text::CSV;
my #template;
open my $field_fh, '<', 'my_field_spec.txt';
while ( <$field_fh> ) {
my (#info) = /\d+/g;
die unless #info == 2;
push #template, sprintf '#%dA%d', #info;
}
my $template = "#template";
open my $source_fh, '<', 'my_source_data.txt';
my $csv = Text::CSV->new( { binary => 1, eol => $/ } );
while ( <$source_fh> ) {
my #fields = unpack $template;
$csv->print(\*STDOUT, \#fields);
}
output
12345678,ABCDE,1234,FGHIJK
It looks like you're slightly confused on how to read the contents of the COMMA filehandle.. Each time you read <COMMA>, you're reading another line from that file. Instead, read a line into a scalar like my $line = <FH> and use that instead:
while (my $source_line = <SOURCE>) {
$StartPosition = 0;
$Length = 0;
$Output = "";
$Input = $_;
$NextRecord ="";
while (my $comma_line = <COMMA>) {
my $Comma = index($comma_line, ',');
print "Comma location found at $Comma \n";
$StartPosition = substr($comma_line, 0, $Comma);
print "Start position is $StartPosition \n";
$Length = substr($comma_line, $Comma);
print "Length is $Length \n";
$NextRecord = substr($Input, $StartPosition, $Length) + ',';
$Output = "$Output$NextRecord";
}
print OUTPUT "$Output \n";
}

Extract email-ids and names using perl

I'm trying to write a Perl script to parse a directory full of emails and names and extract an email address and corresponding name.
At the moment I'm parsing for the word Email Address : and then extracting the line, but this is where I am stuck.
The data is in the following format:
Name :John van
Email Address :john#abc.com
I need to get this data into two variables like $name and $email.
Is there a better way to parse the files to get the email address and name? How do I deal with the strings and re arrange them.
Can anyone help please?
data: (the \n is only implicit for understanding)
Name :John van\n
\n
Email Address :john#abc.com\n
\n
regex based:
use Data::Dumper;
my #data = m/Name\s*:([A-Za-z\s]*)\n\nEmail Address\s*:([A-Za-z\s]*#[A-Za-z\s]*.[A-Za-z]*)\n/g;
print Dumper #data;
will give
$VAR = [
John van,
john#abc.com
]
if you want to do it line based, my approach would be: (not tested - sharpshoot) :)
my #data = (
'Name :john van',
'',
'Email Address :john#abc.com',
''
);
my (#persons, $name, $email);
my $gotName = 0;
my $gotEmail = 0;
while(#data) { # data is your read in filehandle
if (/^Name/) {
$name = $_;
$name =~ s/.*://;
chomp($name);
$gotName++;
}
if (/^Email/) {
$mail= $_;
$mail=~ s/.*://;
chomp($mail);
$gotEmail++;
}
if ($gotName == 1 and $gotEmail == 1) {
push(#persons, ($name,$email));
$gotName = 0;
$gotEmail = 0;
}
}
Is there a better way to parse the files to get the email address and
name?
a better way as which one?
How do I deal with the strings and re arrange them.
what is the question?
There's definitely an easier way of doing this but try:
From Input:
Name: John Van
Email Address: john#abc.com
Name: John Doe
Email Address: johnD#123.com
#!/usr/bin/perl
use warnings;
use strict;
my $emails = 'email.txt';
open my $input, '<', $emails or die "Can't open $emails: $!";
my (%data, #name, #email);
while(<$input>){
push #name, $1 if /Name:\s+(.*)/;
push #email, $1 if /Email Address:\s+(.*)/;
$data{$name[$_]} = $email[$_] for 0 .. $#name;
}
for my $name (keys %data){
my $email = $data{$name};
print "$name\t$email\n"
}
Outputs:
John Doe johnD#123.com
John Van john#abc.com

Name multiple variables using STDIN

I'm trying to use to read in user input to a programme as follows:
#!/usr/bin/perl -w
use strict;
if ($#ARGV == 0) {
print "What condition are you sorting?\t";
chomp(my $condition = <STDIN>);
# Use $condition in further blocks of code...
}
This is working. However When I can't work out how to enter 2 (or more) values to be used in a similar fashion. E.g
if ($#ARGV == 1) {
print "What conditions are you comparing?\t";
chomp(my $condition1 = <STDIN>);
chomp(my $condition2 = <STDIN>);
Allows me to input twice, but the formatting is distorted:
What conditions are you comparing? <condition1>
<condition2>
You can enter conditions separated by comma or white space to preserve formatting,
chomp(my $input = <STDIN>);
my ($condition1, $condition2) = split /[\s,]+/, $input;