How do I compare two strings using Perl - perl

I have googled until I ran out of options. I must be doing something wrong but I cannot figure out what. (obviously I am new to Perl and inherited this project).
I am just trying to see if a variable is equal to 'Y'. As you can see towards the bottom of the code below, I have tried 'eq', '=' and '=='. Other than setting a new variable equal to the result of an 'eq' operation, all the attempts result in the page blowing up. The result of the string test ($stringtest) appears to be empty and I would not know how to test it if it wasn't.
#!/usr/bin/perl -w
#######################################################################
# Test script to show how we can pass in the needed information
# to a web page and use it to run a program on the webserver and
# redirect its output to a text file.
#######################################################################
require 5; #Perl 5 or greater
require "jwshttputil.pl";
require "jwsdbutil.pl";
# Parse QUERY_STRING
&HTTPGet;
# Parse POST_STRING - NOTE: This CLEARS the post data
&HTTPPost;
print STDOUT "Content-type: text/html\n\n";
print STDOUT "<HTML><BODY>";
$canrun = "Y";
$is4ge = $Data{'is4ge'};
$sYes = "Y";
#Step 1: Check for needed values
if ( !($Data{'user'}) )
{
print "user was not found<br/>";
$canrun = "N";
}
if ( !($Data{'pwd'}) )
{
print "pwd was not found<br/>";
$canrun = "N";
}
if ( !($Data{'is4ge'}) )
{
print "is4ge was not found<br/>";
$canrun = "N";
}
print "$Data{'is4ge'}"; #prints Y
print $is4ge; #prints Y
if ( !($Data{'db'}) )
{
print "db was not found<br/>";
#if (!($is4ge = "Y")) #dies
# $canrun = "N";
#if (!($is4ge eq "Y")) #dies
# $canrun = "N";
#$stringtest = ($is4ge eq $sYes);
#print $stringtest; #displays nothing
#if (($is4ge == $sYes)) #dies
# $canrun = "N";
}
print STDOUT "</BODY></HTML>";

You have a good answer to your question, but it might be useful to point out how you could have investigated this yourself.
Firstly, your original title for this question was "How do I compare two strings in a CGI page under Apache?" That title has been corrected because this problem has nothing to do with CGI or Apache, it's simply a misunderstanding about Perl syntax. I know you couldn't have known that initially, but a good way to investigate strange errors like this is to eliminate as many of the complications as possible. So forget about CGI and web servers - just write a simple Perl program.
#!/usr/bin/perl
$canrun = 'N';
$is4ge = 'Y';
if (!$is4ge eq 'Y')
$canrun = 'Y';
print $canrun;
Running this, we get:
$ perl testif
Scalar found where operator expected at testif line 7, near ")
$canrun"
(Missing operator before $canrun?)
syntax error at testif line 7, near ")
$canrun "
Execution of testif aborted due to compilation errors.
That makes it clear that the problem is the syntax around lines 6 and 7. That might be enough to send you off to the Perl syntax manual page, where you would learn that condition statements in Perl always require braces around the block. If not, you could add the diagnostics pragma to get more information.
So as you've already been told, the correct format for your test is
if ($is4ge ne 'Y') {
$canrun = 'Y';
}
But there are a few other things in this program that will make it hard to maintain in the future. Basically, it is rather falling behind with Perl best practices.
You use -w when that was replaced with use warnings in Perl 5.6.0 (released in 2000)
You don't have use strict in the code (that will point out many bad practices in your code which you'll want to fix - in particular, you'll need to declare your variables).
The two libraries that are required at the top of the program might well be better rewritten as proper Perl modules.
I worry that jwshttpdutil.pl might be a home-baked CGI parser that should be replaced with CGI.pm.
The embedded HTML in the code should be replaced with a templating engine of some kind.
Also, I recommend reading CGI::Alternatives to bring yourself up to date with modern Perl methods for writing web applications. You are using techniques that were out of date before the end of the last millennium.

Curlies around the body of flow control statements are not optional in Perl.
eq is indeed the string comparison operator in Perl.
So,
if (!($is4ge eq "Y")) {
$canrun = "N";
}
Or just
if ($is4ge ne "Y") {
$canrun = "N";
}
You really should be using 1 and 0 instead of 'Y' and 'N', since they are true and a false values that can more easily be tested.

Related

Perl CGI produces unexpected output

I have a Perl CGI script for online concordance application that searches for an instance of word in a text and prints the sorted output.
#!/usr/bin/perl -wT
# middle.pl - a simple concordance
# require
use strict;
use diagnostics;
use CGI;
# ensure all fatals go to browser during debugging and set-up
# comment this BEGIN block out on production code for security
BEGIN {
$|=1;
print "Content-type: text/html\n\n";
use CGI::Carp('fatalsToBrowser');
}
# sanity check
my $q = new CGI;
my $target = $q->param("keyword");
my $radius = $q->param("span");
my $ordinal = $q->param("ord");
my $width = 2*$radius;
my $file = 'concordanceText.txt';
if ( ! $file or ! $target ) {
print "Usage: $0 <file> <target>\n";
exit;
}
# initialize
my $count = 0;
my #lines = ();
$/ = ""; # Paragraph read mode
# open the file, and process each line in it
open(FILE, " < $file") or die("Can not open $file ($!).\n");
while(<FILE>){
# re-initialize
my $extract = '';
# normalize the data
chomp;
s/\n/ /g; # Replace new lines with spaces
s/\b--\b/ -- /g; # Add spaces around dashes
# process each item if the target is found
while ( $_ =~ /\b$target\b/gi ){
# find start position
my $match = $1;
my $pos = pos;
my $start = $pos - $radius - length($match);
# extract the snippets
if ($start < 0){
$extract = substr($_, 0, $width+$start+length($match));
$extract = (" " x -$start) . $extract;
}else{
$extract = substr($_, $start, $width+length($match));
my $deficit = $width+length($match) - length($extract);
if ($deficit > 0) {
$extract .= (" " x $deficit);
}
}
# add the extracted text to the list of lines, and increment
$lines[$count] = $extract;
++$count;
}
}
sub removePunctuation {
my $string = $_[0];
$string = lc($string); # Convert to lowercase
$string =~ s/[^-a-z ]//g; # Remove non-aplhabetic characters
$string =~ s/--+/ /g; #Remove 2+ hyphens with a space
$string =~s/-//g; # Remove hyphens
$string =~ s/\s=/ /g;
return($string);
}
sub onLeft {
#USAGE: $word = onLeft($string, $radius, $ordinal);
my $left = substr($_[0], 0, $_[1]);
$left = removePunctuation($left);
my #word = split(/\s+/, $left);
return($word[-$_[2]]);
}
sub byLeftWords {
my $left_a = onLeft($a, $radius, $ordinal);
my $left_b = onLeft($b, $radius, $ordinal);
lc($left_a) cmp lc($left_b);
}
# process each line in the list of lines
print "Content-type: text/plain\n\n";
my $line_number = 0;
foreach my $x (sort byLeftWords #lines){
++$line_number;
printf "%5d",$line_number;
print " $x\n\n";
}
# done
exit;
The perl script produces expected result in terminal (command line). But the CGI script for online application produces unexpected output. I cannot figure out what mistake I am making in the CGI script. The CGI script should ideally produce the same output as the command line script. Any suggestion would be very helpful.
Command Line Output
CGI Output
The BEGIN block executes before anything else and thus before
my $q = new CGI;
The output goes to the server process' stdout and not to the HTTP stream, so the default is text/plain as you can see in the CGI output.
After you solve that problem you'll find that the output still looks like a big ugly block because you need to format and send a valid HTML page, not just a big block of text. You cannot just dump a bunch of text to the browser and expect it to do anything intelligent with it. You must create a complete HTML page with tags to layout your content, probably with CSS as well.
In other words, the output required will be completely different from the output when writing only to the terminal. How to structure it is up to you, and explaining how to do that is out of scope for StackOverflow.
As the other answers state, the BEGIN block is executed at the very start of your program.
BEGIN {
$|=1;
print "Content-type: text/html\n\n";
use CGI::Carp('fatalsToBrowser');
}
There, you output an HTTP header Content-type: text/html\n\n. The browser sees that first, and treats all your output as HTML. But you only have text. Whitespace in an HTML page is collapsed into single spaces, so all your \n line breaks disappear.
Later, you print another header, the browser cannot see that as a header any more, because you already had one and finished it off with two newlines \n\n. It's now too late to switch back to text/plain.
It is perfectly fine to have a CGI program return text/plain and just have text without markup be displayed in a browser when all you want is text, and no colors or links or tables. For certain use cases this makes a lot of sense, even if it doesn't have the hyper in Hypertext any more. But you're not really doing that.
Your BEGIN block serves a purpose, but you are overdoing it. You're trying to make sure that when an error occurs, it gets nicely printed in the browser, so you don't need to deal with the server log while developing.
The CGI::Carp module and it's functionality fatalsToBrowser bring their own mechanism for that. You don't have to do it yourself.
You can safely remove the BEGIN block and just put your use CGI::CARP at the top of the script with all the other use statements. They all get run first anyway, because use gets run at compile time, while the rest of your code gets run at run time.
If you want, you can keep the $|++, which turns off the buffering for your STDOUT handle. It gets flushed immediately and every time you print something, that output goes directly to the browser instead of collecting until it's enough or there is a newline. If your process runs for a long time, this makes it easier for the user to see that stuff is happening, which is also useful in production.
The top of your program should look like this now.
#!/usr/bin/perl -T
# middle.pl - a simple concordance
use strict;
use warnigns;
use diagnostics;
use CGI;
use CGI::Carp('fatalsToBrowser');
$|=1;
my $q = CGI->new;
Finally, a a few quick words on the other parts I deleted from there.
Your comment requires over the use statements is misleading. Those are use, not require. As I said above, use gets run at compile time. require on the other hand gets run at run time and can be done conditionally. Misleading comments will make it harder for others (or you) to maintain your code later on.
I removed the -w flag from the shebang (#!/usr/bin/perl) and put the use warnings pragma in. That's a more modern way to turn on warnings, because sometimes the shebang can be ignored.
The use diagnostics pragma gives you extra long explanations when things go wrong. That's useful, but also extra slow. You can use it during development, but please remove it for production.
The comment sanity check should be moved down under the CGI instantiation.
Please use the invocation form of new to instantiate CGI, and any other classes. The -> syntax will take care of inheritance properly, while the old new CGI cannot do that.
I ran your cgi. The BEGIN block is run regardless and you print a content-type header here - you have explicitly asked for HTML here. Then later you attemp to print another header for PLAIN. This is why you can see the header text (that hasn't taken effect) at the beginning of the text in the browser window.

Perl else error

Hello I am new to programming in perl I am trying to make a number adder (math) but it gives me 1 error here's my code:
sub main {
print("First: ");
$num1 = <STDIN>;
print("Second: ");
$num2 = <STDIN>;
$answer = $num1 + $num2;
print("$answer")
} else {
print("You have entered invalid arguments.")
}
main;
now obviously its not done but I get an error on ONLY else here is the error:
C:\Users\aries\Desktop>"Second perl.pl"
syntax error at C:\Users\aries\Desktop\Second perl.pl line 9, near "} else"
Execution of C:\Users\aries\Desktop\Second perl.pl aborted due to compilation errors.
please help (also I tried googling stuff still error)
Since you're new to Perl, I recommend you add strict and warnings at the top of your scripts. This will help identify common problems and potentially dangerous code.
The main problem with your code is that you've appended the else statement to your subroutine. Here is an example of your code as I think you intended it to be:
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);
sub main {
print 'First :';
my $num1 = <STDIN>;
print 'Second: ';
my $num2 = <STDIN>;
if( looks_like_number($num1) && looks_like_number($num2) ) {
my $answer = $num1 + $num2;
print "$answer\n";
}
else {
die 'You have entered invalid arguments.';
}
}
main();
There are a few things I should note here about the differences between Perl and Python that I think will help you understand Perl better.
Unlike Python, Perl doesn't care about white space. It uses curly braces and semi-colons to indicate the end of blocks and statements and will happily ignore any white space that isn't in quotes.
The else statement appended to the subroutine won't work because Perl isn't designed to evaluate code blocks that way. A subroutine is simply a named code block that can be called at any other point in the script. Any error handling will need to be done inside of the subroutine rather than to it.
Perl is very context-sensitive and doesn't make a solid distinction between strings and integers in variables. If you write $var_a = 1, Perl will read it as an integer. $var_b = '1', it will read it as a string. But, you can still add them together: $var_c = ($var_a + $var_b), and Perl will make $var_c = 2.
This is another reason the else statement would not work as you've written it. Python would throw an error if you try to add non-integers, but Perl will just figure out how to combine them, and give you the result. If you try to add a letter and a number, Perl still won't fail, but it will warn you if you put "use warnings;" at the top of your script.
In the example, and as Dada mentioned, you can use the looks_like_number() method from the Scalar::Utils module to evaluate the variables as you had intended.
Apart from the syntax, if/else statements work the same way in Perl as in Python. The else-if is slightly different as is has an extra s:
if (condition) {
...
}
elsif (other condition) {
...
}
else {
...
}
In Perl, it's good practice to assign lexical scope to variables using the my function. Since Perl is so context-sensitive, this can help prevent unexpected behavior when moving between different scopes.
Single- and double-quotes have different uses in Perl. Single-quotes are read literally and double-quotes are interpolated, so if you want to combine variables and text together, you can skip concatenating the strings and just do: print "Got variable: $var\n";
Lastly, note that I added parentheses after the main subroutine call. This is another best practice to make it clearer that you are calling a subroutine as opposed to it being a bare word or a bad variable name.

Perl - How to create commands that users can input in console?

I'm just starting in Perl and I'm quite enjoying it. I'm writing some basic functions, but what I really want to be able to do is to use those functions intelligently using console commands. For example, say I have a function adding two numbers. I'd want to be able to type in console "add 2, 4" and read the first word, then pass the two numbers as parameters in an "add" function. Essentially, I'm asking for help in creating some basic scripting using Perl ^^'.
I have some vague ideas about how I might do this in VB, but Perl, I have no idea where I'd start, or what functions would be useful to me. Is there something like VB.net's "Split" function where you can break down the contents of a scalar into an array? Is there a simple way to analyse one word at a time in a scalar, or iterate through a scalar until you hit a separator, for example?
I hope you can help, any suggestions are appreciated! Bear in mind, I'm no expert, I started Perl all of a few weeks ago, and I've only been doing VB.net half a year.
Thank you!
Edit: If you're not sure what to suggest and you know any simple/intuitive resources that might be of help, that would also be appreciated.
Its rather easy to make a script which dispatches to a command by name. Here is a simple example:
#!/usr/bin/env perl
use strict;
use warnings;
# take the command name off the #ARGV stack
my $command_name = shift;
# get a reference to the subroutine by name
my $command = __PACKAGE__->can($command_name) || die "Unknown command: $command_name\n";
# execute the command, using the rest of #ARGV as arguments
# and print the return with a trailing newline
print $command->(#ARGV);
print "\n";
sub add {
my ($x, $y) = #_;
return $x + $y;
}
sub subtract {
my ($x, $y) = #_;
return $x - $y;
}
This script (say its named myscript.pl) can be called like
$ ./myscript.pl add 2 3
or
$ ./myscript.pl subtract 2 3
Once you have played with that for a while, you might want to take it further and use a framework for this kind of thing. There are several available, like App::Cmd or you can take the logic shown above and modularize as you see fit.
You want to parse command line arguments. A space serves as the delimiter, so just do a ./add.pl 2 3 Something like this:
$num1=$ARGV[0];
$num2=$ARGV[1];
print $num1 + $num2;
will print 5
Here is a short implementation of a simple scripting language.
Each statement is exactly one line long, and has the following structure:
Statement = [<Var> =] <Command> [<Arg> ...]
# This is a regular grammar, so we don't need a complicated parser.
Tokens are seperated by whitespace. A command may take any number of arguments. These can either be the contents of variables $var, a string "foo", or a number (int or float).
As these are Perl scalars, there is no visible difference between strings and numbers.
Here is the preamble of the script:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
strict and warnings are essential when learning Perl, else too much weird stuff would be possible. The use 5.010 is a minimum version, it also defines the say builtin (like a print but appends a newline).
Now we declare two global variables: The %env hash (table or dict) associates variable names with their values. %functions holds our builtin functions. The values are anonymous functions.
my %env;
my %functions = (
add => sub { $_[0] + $_[1] },
mul => sub { $_[0] * $_[1] },
say => sub { say $_[0] },
bye => sub { exit 0 },
);
Now comes our read-eval-loop (we don't print by default). The readline operator <> will read from the file specified as the first command line argument, or from STDIN if no filename is provided.
while (<>) {
next if /^\s*\#/; # jump comment lines
# parse the line. We get a destination $var, a $command, and any number of #args
my ($var, $command, #args) = parse($_);
# Execute the anonymous sub specified by $command with the #args
my $value = $functions{ $command }->(#args);
# Store the return value if a destination $var was specified
$env{ $var } = $value if defined $var;
}
That was fairly trivial. Now comes some parsing code. Perl “binds” regexes to strings with the =~ operator. Regexes may look like /foo/ or m/foo/. The /x flags allows us to include whitespace in our regex that doesn't match actual whitespace. The /g flag matches globally. This also enables the \G assertion. This is where the last successful match ended. The /c flag is important for this m//gc style parsing to consume one match at a time, and to prevent the position of the regex engine in out string to being reset.
sub parse {
my ($line) = #_; # get the $line, which is a argument
my ($var, $command, #args); # declare variables to be filled
# Test if this statement has a variable declaration
if ($line =~ m/\G\s* \$(\w+) \s*=\s* /xgc) {
$var = $1; # assign first capture if successful
}
# Parse the function of this statement.
if ($line =~ m/\G\s* (\w+) \s*/xgc) {
$command = $1;
# Test if the specified function exists in our %functions
if (not exists $functions{$command}) {
die "The command $command is not known\n";
}
} else {
die "Command required\n"; # Throw fatal exception on parse error.
}
# As long as our matches haven't consumed the whole string...
while (pos($line) < length($line)) {
# Try to match variables
if ($line =~ m/\G \$(\w+) \s*/xgc) {
die "The variable $1 does not exist\n" if not exists $env{$1};
push #args, $env{$1};
}
# Try to match strings
elsif ($line =~ m/\G "([^"]+)" \s*/xgc) {
push #args, $1;
}
# Try to match ints or floats
elsif ($line =~ m/\G (\d+ (?:\.\d+)? ) \s*/xgc) {
push #args, 0+$1;
}
# Throw error if nothing matched
else {
die "Didn't understand that line\n";
}
}
# return our -- now filled -- vars.
return $var, $command, #args;
}
Perl arrays can be handled like linked list: shift removes and returns the first element (pop does the same to the last element). push adds an element to the end, unshift to the beginning.
Out little programming language can execute simple programs like:
#!my_little_language
$a = mul 2 20
$b = add 0 2
$answer = add $a $b
say $answer
bye
If (1) our perl script is saved in my_little_language, set to be executable, and is in the system PATH, and (2) the above file in our little language saved as meaning_of_life.mll, and also set to be executable, then
$ ./meaning_of_life
should be able to run it.
Output is obviously 42. Note that our language doesn't yet have string manipulation or simple assignment to variables. Also, it would be nice to be able to call functions with the return value of other functions directly. This requires some sort of parens, or precedence mechanism. Also, the language requires better error reporting for batch processing (which it already supports).

Perl script for creating two arrays

Input: A list of numbers on command line
Output: Two lists of numbers ,one with input numbers that are greater than zero and one with those that are less than zero (Ignoring zero valued numbers)
here is my code
#!/usr/bin/perl
$i++ = 0;
$j++ = 0;
while ($number = <>)
{
if($number<0)
$first[$i++]=$number;
else
$second[$j++]=$number;
}
print "The numbers with value less than zero are\n";
foreach $number (#first)
print $number;
print "The numbers with value greater than zero are\n"
foreach $number(#second)
print $number;
I am getting the following silly errors which i am not able to rectify.The errors are
divide.pl: 2: ++: not found
divide.pl: 3: ++: not found
divide.pl: 5: Syntax error: ")" unexpected
Can anybody help me out with rectifying these errors please? I am new to perl script
Curly braces on compound statements are not optional in Perl.
Your statements:
$i++=0;
$j++=0;
don't make sense; you probably just want to delete the "++".
You're missing a semicolon on one of your print statements.
Once you've got those problems fixed, you should add
use strict;
use warnings;
after the #! line. This will introduce more error messages; you'll need to fix those as well. For example, you'll need to declare your variables using my().
The code you present will hardly compile. Loops should have {} around the main block, arrays are better created with push (or unshift), you should use strict and warnings, and you can't do increments at the same time as assignments (e.g. $i++ = 0).
use v5.10;
use strict;
use warnings;
my (#first, #second);
while (<STDIN>) { # <STDIN> clearer than <> in this case
chomp;
if ($_ < 0) {
push #first, $_;
} elsif ($_ > 0) {
push #second, $_;
}
}
say "Numbers less than zero:";
say "#first";
say "Numbers greater than zero:";
say "#second";
I don't know what $i++ = 0 is supposed to mean, but change that to $i = 0 to initialize the variables.
Also, the first thing yuu should do in the while loop is call chomp($number) to remove spurious newlines - 5\n is not a number and treating it as one will confuse perl.
Once you've fixed that, post any new errors that show up - I don't see any other problems though.
How are you executing this perl script? Beyond the errors mentioned about the code itself. It looks like you are attempting to evaluate the code using dash instead of perl.
The errors you should be seeing if you were executing it with Perl would be like:
Can't modify postincrement (++) in scalar assignment at /tmp/foo.pl
line 2, near "0;"
But instead, your errors are more in line with what dash outputs:
$ dash /tmp/foo.pl
/tmp/foo.pl: 2: ++: not found
/tmp/foo.pl: 3: ++: not found
Once you've verified that you are running your perl script properly you can start working through the other problems people have mentioned your code. The easiest way to do this is to run it via perl divide.pl instead of whatever you are doing.

Perl comparison operation between a variable and an element of an array

I am having quite a bit of trouble with a Perl script I am writing. I want to compare an element of an array to a variable I have to see if they are true. For some reason I cannot seem to get the comparison operation to work correctly. It will either evaluate at true all the time (even when outputting both strings clearly shows they are not the same), or it will always be false and never evaluate (even if they are the same). I have found an example of just this kind of comparison operation on another website, but when I use it it doesn't work. Am I missing something? Is the variable type I take from the file not a string? (Can't be an integer as far as I can tell as it is an IP address).
$ipaddress = '192.43.2.130'
if ($address[0] == ' ')
{
open (FH, "serverips.txt") or die "Crossroads could not find a list of backend servers";
#address = <FH>;
close(FH);
print $address[0];
print $address[1];
}
for ($i = 0; $i < #address; $i++)
{
print "hello";
if ($address[$i] eq $ipaddress)
{print $address[$i];
$file = "server_$i";
print "I got here first";
goto SENDING;}
}
SENDING:
print " I am here";
I am pretty weak in Perl, so forgive me for any rookie mistakes/assumptions I may have made in my very meager bit of code. Thank you for you time.
if ($address[0] == ' ')
{
open (FH, "serverips.txt") or die "Crossroads could not find a list of backend servers";
#address = <FH>;
close(FH);
You have several issues with this code here. First you should use strict because it would tell you that #address is being used before it's defined and you're also using numeric comparison on a string.
Secondly you aren't creating an array of the address in the file. You need to loop through the lines of the file to add each address:
my #address = ();
while( my $addr = <FH> ) {
chomp($addr); # removes the newline character
push(#address, $addr);
}
However you really don't need to push into an array at all. Just loop through the file and find the IP. Also don't use goto. That's what last is for.
while( my $addr = <FH> ) {
chomp($addr);
if( $addr eq $ipaddress ) {
$file = "server_$i";
print $addr,"\n";
print "I got here first"; # not sure what this means
last; # breaks out of the loop
}
}
When you're reading in from a file like that, you should use chomp() when doing a comparison with that line. When you do:
print $address[0];
print $address[1];
The output is on two separate lines, even though you haven't explicitly printed a newline. That's because $address[$i] contains a newline at the end. chomp removes this.
if ($address[$i] eq $ipaddress)
could read
my $currentIP = $address[$i];
chomp($currentIP);
if ($currentIP eq $ipaddress)
Once you're familiar with chomp, you could even use:
chomp(my $currentIP = $address[$i]);
if ($currentIP eq $ipaddress)
Also, please replace the goto with a last statement. That's perl's equivalent of C's break.
Also, from your comment on Jack's answer:
Here's some code you can use for finding how long it's been since a file was modified:
my $secondsSinceUpdate = time() - stat('filename.txt')->mtime;
You probably are having an issue with newlines. Try using chomp($address[$i]).
First of all, please don't use goto. Every time you use goto, the baby Jesus cries while killing a kitten.
Secondly, your code is a bit confusing in that you seem to be populating #address after starting the if($address[0] == '') statement (not to mention that that if should be if($address[0] eq '')).
If you're trying to compare each element of #address with $ipaddress for equality, you can do something like the following
Note: This code assumes that you've populated #address.
my $num_matches=0;
foreach(#address)
{
$num_matches++ if $_ eq $ipaddress;
}
if($num_matches)
{
#You've got a match! Do something.
}
else
{
#You don't have any matches. This may or may not be bad. Do something else.
}
Alternatively, you can use the grep operator to get any and all matches from #address:
my #matches=grep{$_ eq $ipaddress}#address;
if(#matches)
{
#You've got matches.
}
else
{
#Sorry, no matches.
}
Finally, if you're using a version of Perl that is 5.10 or higher, you can use the smart match operator (ie ~~):
if($ipaddress~~#address)
{
#You've got a match!
}
else
{
#Nope, no matches.
}
When you read from a file like that you include the end-of-line character (generally \n) in each element. Use chomp #address; to get rid of it.
Also, use last; to exit the loop; goto is practically never needed.
Here's a rather idiomatic rewrite of your code. I'm excluding some of your logic that you might need, but isn't clear why:
$ipaddress = '192.43.2.130'
open (FH, "serverips.txt") or die "Crossroads could not find a list of backend servers";
while (<FH>) { # loop over the file, using the default input space
chomp; # remove end-of-line
last if ($_ eq $ipaddress); # a RE could easily be used here also, but keep the exact match
}
close(FH);
$file = "server_$."; # $. is the line number - it's not necessary to keep track yourself
print "The file is $file\n";
Some people dislike using perl's implicit variables (like $_ and $.) but they're not that hard to keep track of. perldoc perlvar lists all these variables and explains their usage.
Regarding the exact match vs. "RE" (regular expression, or regexp - see perldoc perlre for lots of gory details) -- the syntax for testing a RE against the default input space ($_) is very simple. Instead of
last if ($_ eq $ipaddress);
you could use
last if (/$ipaddress/);
Although treating an ip address as a regular expression (where . has a special meaning) is probably not a good idea.