I have a program here that will allow user to enter in words that will be used as filenames later on. The user's input is inserted into an array. I then create a simple menu asking what the user wants to do with the "filename": create, reame, copy, and delete. Using subroutines, I believe I've successfully executed the code. However, I am having trouble trying to reference the array element.
In short, how do I create, rename, copy, and delete the filenames that are saved in the array? The issues I cant resolve are asterisked
#!/usr/bin/perl
use strict;
use warnings;
use File::Copy qw/copy/;
my $new;
my $old;
my $file;
print "Enter number of lines\n";
chomp(my $n = <STDIN>);
my #lines;
print "Enter some words!\n";
for (1..$n) {
chomp(my $input = <STDIN>);
#will add the user input at the beginning of the array
push #lines, $input;
}
print "#lines\n";
#create a menu
my $in = '';
print "1. Create\n2. Rename\n3. Copy\n4. Delete\n5. Quit\n";
while ($in ne "quit")
{
print "\nEnter the your choice:\n";
chomp($in = <STDIN>);
print "For which file do you want to $in?\n";
print "#lines\n";
**#I need to reference the array here***********************
if ($in eq "create") {
***How to create the file that the user inputted?*****************
&createFile;
print "\nFile has been created\n";
}
elsif ($in eq "rename") {
#print "Enter the old name\n";
# chomp($old = <STDIN>);
#*********refer to array of FILES*********************
print "Enter the new name for this file!\n";
chomp($new = <STDIN>);
&renameFile;
print "File has successfully been renamed.";
}
elsif ($in eq "copy") {
#********file and array refering***************************
©File;
print "Hopefully, the file has beed copied!";
}
elsif ($in eq "delete") {
#******refer to file from user*******************
&deleteFile;
print "Deleted";
}
}
#create subroutine
sub createFile {
open('>' .*****issue here too**) or die "\nCannot create";
}
sub renameFile {
rename ($old, $new);
}
sub copyFile {
copy $old, $new;
}
sub deleteFile {
#unlink *****************************
}
First line is $line[0], second is $line[1] and so on...
You can get user choice like this:
$line[$in]
About how to refer to perl data structures see here
$lines[0]; #First line
$lines[1]; #Second line
$array = \#lines; # Get reference to the list of lines
$array->[0]; #First line
$array->[1]; #Second line
to create file and put data into just use:
open $fh, '>filename';
print $fh #lines;
print $fh #$array; # ... or same for reference
Notice lack of coma after $fh
Related
The problem with code is petlist2_out has last lines of petlist1_out when inputfile1 has more lines than inputfile2. it looks like array passed by reference is to function and copied back is keeping older array content. Please help. the code is working perfectly for all other cases. i am not sure on how to clean the arrays and varaibles other than using undef. When using references how to avoid using same location when function is called multiple times?
i am not a professional in Perl coding.
use File::Basename;
#use warnings;
if ($#ARGV != 1 )
{
print "usage: sort_petlist_extract.pl old-petlist new-petlist";
exit;
}
print "\n****** Reading petlist .....\n";
$inputfile1 = shift(#ARGV); #get text based IN filename
$inputfile2 = shift(#ARGV); #get text based IN filename
my $result = dirname $inputfile2;
print $result;
#my $filename = basename $filespec;
#$result = 'C:\\temp\\';
#my $inputfile=$ARGV[0];
open(log_file, "> ".$result.'\\'."debug.log");
open(diff_rpt_file, "> ".$result.'\\'."diff_report.txt");
print log_file $inputfile1."\n";
print log_file $inputfile2."\n";
open(petlist1, "< $inputfile1") or die "\nCouldn't open input file\n";
my #input_lines1 = <petlist1>;
close petlist1;
chomp #input_lines1;
#foreach(#input_lines1){print log_file $_."\n";}
my($petlist1_2d_ref)=extract_petlist_file(\#input_lines1);
my %petArray1 = %{$petlist1_2d_ref};
undef #input_lines1;
print log_file $petArray1_ref ."\n";
print scalar keys %petArray1;
open(petlist1_out, "> ".$result.'\\'."petlist1_out.txt");
#just test a display
for($i=0;$i<(scalar keys %petArray1);$i++)#just a display
{
print petlist1_out "${$petArray1{$i}}[0] \t ${$petArray1{$i}}[1] \n";
}
close petlist1_out;
undef %petArray1;
print log_file "###############################################################################first file copied to array#######################################\n";
print "####################first file copied to array########################\n";
open(petlist2, "< $inputfile2") or die "\nCouldn't open input file\n";
my #input_lines2 = <petlist2>;
close petlist2;
chomp #input_lines2;
#foreach(#input_lines2){print log_file $_."\n";}
undef $petlist2_2d_ref;
my($petlist2_2d_ref)=extract_petlist_file(\#input_lines2);
my %petArray2 = %{$petlist2_2d_ref};
#my($page_petname)=extract_page_petname(\#input_lines2);### page number extracttion
undef #input_lines2;
print log_file $petArray2_ref."\n";
print scalar keys %petArray2;
open(petlist2_out, "> ".$result.'\\'."petlist2_out.txt");
#just test a display
for($i=0;$i<(scalar keys %petArray2);$i++)#just a display
{
print petlist2_out "${$petArray2{$i}}[0] \t ${$petArray2{$i}}[1] \n";
}
close petlist2_out;
print log_file "###############################################################################second file copied to array #######################################\n";
print "####################second file copied to array ######################\n";
####################### sub routines
sub extract_petlist_file
{
undef $arr1;
my $arr1=$_[0];
undef #petlist;
my #petlist=#$arr1;
#foreach(#petlist){print log_file $_."\n";}
my $temp1='';
my $temp2='';
undef #temp;#clear 1D array
my #temp;
undef $_petArray;
my $_petArray;
undef $i;
print log_file scalar #petlist."\n";
my $k=0;
my $pattern1='PET_NAME';
for(my $i=0;$i<(scalar #petlist);$i++)
{
#print "$i\n";
#print log_file $_;
$_=$petlist[$i];
if ((m/$pattern1/) && $combine_flag eq 0)# first time ever in the loop
{
}
}
#store the last pet connection to array
#temp=($temp1,$temp2);
$_petArray{$k}=[#temp];
undef #temp;
undef $temp1;
undef $temp2;
return \%_petArray;
}
Thanks for the guidance. The strict and warnings helped. The actual issue was "my $_petArray;" had to be "my %_petArray;". I was using it as a variable instead of declaring as array.
I'm new to programming much less Perl; I'm having difficulty with searching an array I've made from an external text file. I'm looking for a simple way to check if the user entry is located in the array. I've used the Smart Match function before but never in an "if" statement and can't seem to get it to work. Am I implementing this function wrong, or is there an easier way to check if the user's string is in the array?
#!/usr/bin/perl
use 5.010;
#Inventory editing script - Jason Black
#-------------------------------------------------------------------------------
print "1. Add Items\n";
print "2. Search Items\n";
print "Please enter your choice: ";
chomp ($userChoice = <STDIN>); #Stores user input in $userChoice
if($userChoice == 1){
$message = "Please enter in format 'code|title|price|item-count'\n";
&ChoiceOne;
}
elsif($userChoice == 2){
$message = "Enter search terms\n";
&ChoiceTwo;
}
sub ChoiceOne{
print "$message\n";
chomp($userAddition = <STDIN>); #Stores input in $userAddition
$string1 = "$userAddition";
open (FILE, "FinalProjData.txt") or die ("File not found"); #"FILE" can be named anything
#array = <FILE>;
if ( /$string1/ ~~ #array){
print "This entry already exists. Would you like to replace? Y/N \n";
chomp($userDecision = <STDIN>); #Stores input in $userDecision
if ($userDecision eq "Y"){
$string1 =~ s/$userAddition/$userAddition/ig;
print "Item has been overwritten\n";}
elsif($userDecision eq "N"){
print FILE "$string1\n";
print "Entry has been added to end of file.\n";}
else{
print "Invalid Input";
exit;}
}
else {
print FILE "$string1\n";
print "Item has been added.\n";}
close(FILE);
exit;
}#end sub ChoiceOne
sub ChoiceTwo{
print "$message\n";
}
If you want to avoid using smartmatch alltogether:
if ( grep { /$string1/ } #array ) {
To actually match the $string1, however, it needs to be escaped, so that | doesn't mean or:
if ( grep { /\Q$string\E/ } #array ) {
or just a simple string compare:
if ( grep { $_ eq $string } #array ) {
yesterday i asked this question and got many helpful replies, hoping the same will be true today. Here is my revised script.
#! /usr/bin/perl
use strict;
use warnings;
my $line;
my #array;
my $print;
open (OUT , ">","output.txt")or die "cant open: $!";
while ($line = <>){
chomp($line);
push(#array, $line);
if(#array == 250){
$print = print "[", join(",",#array), "]", "\n";
print OUT $print;
#array = []
}
}
Originally i simply stated that i need to print out the first 250 elements of an array to a text file, and that this array was built from standard input. What i didnt state is that the input, from which the array is built, may consist of several thousand lines. The reason for creating an array from this input is so that i can limit the size of the array to 250 entities, and then print the array as a formatted string. I then need to flush the array and resume building at what will become the 251st line of the input, and continue doing this process for the remainder of the input. Lets say the input is 5k lines, i want my output to be a text file containing the original 5k lines of input, but divided into strings made up of 250 array entities.
Currently the script is just printing the array to the screen and inside "ouput.txt" is a single line reading: 1111111.
$print = print "[", join(",",#array), "]", "\n";
print OUT $print;
Here you are assigning the return value of print to $print, which is 1, because the printing is successful. What you want to do is this:
print OUT "[", join(",",#array), "]", "\n";
Here's another option which just slightly modifies your script:
use strict;
use warnings;
my #array;
local $" = ',';
while (<>) {
chomp;
push #array, $_;
if ( #array == 250 ) {
print "[#array]\n";
undef #array;
}
}
Usage: perl script.pl Infile [>outFile]
The last, optional parameter directs output to a file.
The variable $" is holds Perl's list separator that's applied to an interpolated array, so join's not needed here.
Hope this helps!
#! /usr/bin/perl
use strict;
use warnings;
my $line;
my #array;
my $print;
open (OUT , ">","moloch_chunker_output.txt")or die "cant open: $!";
while ($line = <>){
chomp($line);
push(#array, $line);
if(#array == 250){
print OUT "[", join(",",#array), "]", "\n";
#array = ();
}
}
Thank you davs, that fixed it.
This is kind of a small issue and I hope you are able to help me. My code is probably rubbish. For an example, I have a file in which the only statement is John is the uncle of Sam. My Perl script should copy the file contents into an array. User should be able to input different names and search if those names are mentioned in the file. There should be an array with relationships like "uncle aunt, mother, father etc" in the program.
#use warnings;
use Array::Utils qw(:all);
print "Please enter the name of the file\n";
my $c = <STDIN>;
open(NEW,$c) or die "The file cannot be opened";
#d = <NEW>;
print #d, "\n";
#g = qw(aunt uncle father);
chomp #d;
chomp #g;
my $e;
my $f;
print "Please enter the name of the first person\n";
my $a = <STDIN>;
print "Please enter the name of the second person\n";
my $b = <STDIN>;
my #isect = intersect(#g, #d);
print #isect;
foreach(#d)
{
if ($a == $_)
{
$e = $a;
}
else
{
print "The first person is not mentioned in the article";
exit();
}
if ($b == $_)
{
$f = $b;
}
else
{
print "The second person is not mentioned in the article";
exit();
}
}
print $e;
print $f;
close(NEW);
This is something that I have done so far, the intersection is not giving the word uncle which is the word common in both arrays. The program is taking any random name and printing them. It is not saying that the name doesn't exist in the file when I enter a different name other than John and Sam
There are several problems:
You do not chomp $c. The filename contains a newline at the end.
You use the 2-argument form of open, but do not test the second argument. This is a security problem: do you know what happens if the user input contains > or |?
You use == to compare strings. String equality is tested with eq, though, == tests numbers.
Moreover, you do not want to know whether "Sam" equals to "John is the uncle of Sam". You want to know whether it is a part of it. You might need to use index or regular expressions to find out.
Do not use $a as the name of a variable, it is special (see perlvar).
Do not try to compare strings with ==! Use eq (equals) instead. Also you didnt chomp your input $a$b`. I think this is what you're trying to do:
#!/usr/bin/perl
use strict;
use warnings;
print "Please enter the name of the file\n";
my $c = <STDIN>;
open(NEW,$c) or die "The file cannot be opened";
my #d = <NEW>;
chomp #d;
my $e;
my $f;
print "Please enter the name of the first person\n";
my $aa = <STDIN>;
print "Please enter the name of the second person\n";
my $bb = <STDIN>;
chomp $aa;
chomp $bb;
my $pattern_a = quotemeta $aa;
my $pattern_b = quotemeta $bb;
foreach (#d){
if ($_ =~ /$pattern_a/){
$e = $aa;
}
elsif ($_ =~ /$pattern_b/){
$f = $bb;
}
}
close(NEW);
unless ($e){
print "First person not mentionend\n";
}
unless ($f){
print "Second person not mentioned\n";
}
The #main::match_to_array prints out only the last element in the array #match_to_array , not the whole array.
I did my code with reference to this SO link.
The input HTML consists of
dmit#sp.com
ems#es.com
dew#es.com
dmit#sp.com
erg#es.com
#!/usr/bin/perl –w
use strict;
use warnings;
use Cwd;
sub extractMail {
my $perl_path = cwd;
# Full HTML.htm
if(-e 'test.html') {
open(OPENFILE, "$perl_path/test.html") or die "Unable to open file";
}
my #email = <OPENFILE>;
close OPENFILE;
foreach my $email (#email){
if ($email =~ /regex to match data/{
my $match = "$1\n";
our #match_to_array = split ("\n",$match);
} # end of if statement
} # end of foreach
} # end of subroutine extractMail
for (my $a = 1;$a<=1;$a++){
&extractMail;
print #main::match_to_array;
}
You have misunderstood the post. The point is to declare the variable at the right place. In this case, you should probably return the value from the subroutine. Moreover, by assigning to an array
#match_to_array = split /\n/, $match;
you are overwriting the previous contents of the array. Use push instead.
Untested:
#!/usr/bin/perl –w
use strict;
use warnings;
use Cwd;
sub extractMail {
my $perl_path = cwd;
if (-e 'test.html') {
open my $OPENFILE, "$perl_path/test.html" or die "Unable to open file: $!";
}
my #match_to_array;
while (my $email = <$OPENFILE>) {
if ($email =~ /regex to match data/) {
my $match = "$1\n";
push #match_to_array, split /\n/, $match;
}
}
return #match_to_array;
}
for my $i (1 .. 1) {
my #match_to_array = extractMail();
print "#match_to_array\n";
}
my #email = <OPENFILE>;
close OPENFILE;
This might be the Problem, after those lines #email is containg one element, namely "dmit#sp.com ems#es.com ...".
Afterwards you're doing this:
foreach my $email (#email)
This will loop once, with
$email = "dmit#sp.com ems#es.com ..."
Then your regex removes everything BUT "dmit#sp.com" and leads you to the conclusion that only one element of your list is processed.
Try reading up on split to generate an array out of your space-separated list