Find words in string - perl

I would like to show in result three words "hidden". I don't know how to do this. Right now, when I start the program, I don't have effect. I see only my text. How to repair it ? I want to create simple program. I have my string and I want to show words which I want to find in my result.
use strict;
my $text='Try to find the hidden string here! Hidden or hidden';
my $a = m/\bhidden\b/;
if ($text=~ $a) {
print "I found word: $a";
}
else {
print "No match, sorry.\n";
}

Let's see how we could debug this problem.
Your first step should be to add use warnings to your code. You should always include both use strict and use warnings. They are like Perl's safety nets and only a foolhardy programmer codes without them.
#!/usr/bin/perl
use strict;
use warnings; # ADDED THIS
my $text='Try to find the hidden string here! Hidden or hidden';
my $a = m/\bhidden\b/;
if ($text=~ $a) {
print "I found word: $a";
}
else {
print "No match, sorry.\n";
}
Now we get a warning:
Use of uninitialized value $_ in pattern match (m//) at test_re line 8.
Line 8 is this:
if ($text=~ $a) {
So let's see what is in $a (as an aside - please don't use $a as a variable name. Firstly, it's a terrible, generic name; and, secondly, Perl uses it as a special variable in the sort function):
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say'; # ADDED THIS
my $text='Try to find the hidden string here! Hidden or hidden';
my $a = m/\bhidden\b/;
say "\$a is [$a]"; # ADDED THIS
if ($text=~ $a) {
print "I found word: $a";
}
else {
print "No match, sorry.\n";
}
Now, as well as our warning, we get this output:
$a is []
I don't think you're expecting $a to be empty at that point, are you? We can go further and determine whether it's an empty string or an undefined value.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text='Try to find the hidden string here! Hidden or hidden';
my $a = m/\bhidden\b/;
say "\$a is [$a]";
say "\$a is ", (defined $a ? 'defined' : 'undefined'); # ADDED THIS
if ($text=~ $a) {
print "I found word: $a";
}
else {
print "No match, sorry.\n";
}
And we see:
$a is defined
So it's an empty string. What do you expect it to be?
Here's where is it set?
my $a = m/\bhidden\b/;
I'm not sure what you expected this to do, but it actually means "match \bhidden\b and assign the result of the match to $a". And what does it match against that regex? Well, m/.../ matches the contents of$` by default. (That, incidentally, explains our original "uninitialized value $" warning - Perl just got the line number wrong by one.)
So what actually happens on that line is that Perl tries to match \bhidden\b against $_. This fails (as $_ is undefined) and the match returns a false value (the empty string) that gets assigned to $a.
Then your code goes on to run this:
if ($text=~ $a) {
And, as $a is the empty string, it matches (any string will match against an empty string and Perl tells you it has matched $a (which still contains the empty string).
I'm not sure what you were trying to do with this line:
my $a = m/\bhidden\b/;
Perhaps you were trying "pre-compile" the regex in some way. In which case, you were looking for qr/.../, not m/.../.
So maybe you wanted this:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text = 'Try to find the hidden string here! Hidden or hidden';
my $a = qr/\bhidden\b/; # CHANGED THIS
say "\$a is [$a]";
say "\$a is ", (defined $a ? 'defined' : 'undefined');
if ($text =~ $a) {
print "I found word: $a";
}
else {
print "No match, sorry.\n";
}
Which gives this output:
$a is [(?^:\bhidden\b)]
$a is defined
I found word: (?^:\bhidden\b)
Or, if you want to show what has been matched, rather than the regex that you are matching, then you need to "capture" that text:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text = 'Try to find the hidden string here! Hidden or hidden';
my $a = qr/\b(hidden)\b/; # CHANGED THIS
say "\$a is [$a]";
say "\$a is ", (defined $a ? 'defined' : 'undefined');
if (my ($matched) = $text =~ $a) { # CHANGED THIS
print "I found word: $matched"; # CHANGED THIS
}
else {
print "No match, sorry.\n";
}
Which gives us:
$a is [(?^:\b(hidden)\b)]
$a is defined
I found word: hidden
Ah, but you want to see all of the words. So capture the matches in an array and use the /g option to match multiple times:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text = 'Try to find the hidden string here! Hidden or hidden';
my $a = qr/\b(hidden)\b/;
say "\$a is [$a]";
say "\$a is ", (defined $a ? 'defined' : 'undefined');
if (my (#matched) = $text =~ /$a/g) { # CHANGED THIS
print "I found word: #matched"; # CHANGED THIS
}
else {
print "No match, sorry.\n";
}
We now get this:
$a is [(?^:\b(hidden)\b)]
$a is defined
I found word: hidden hidden
That only matches two instances of "hidden" as the match is case-sensitive. So turn off the case sensitivity with /i.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text = 'Try to find the hidden string here! Hidden or hidden';
my $a = qr/\b(hidden)\b/i; # CHANGED THIS
say "\$a is [$a]";
say "\$a is ", (defined $a ? 'defined' : 'undefined');
if (my (#matched) = $text =~ /$a/g) {
print "I found word: #matched";
}
else {
print "No match, sorry.\n";
}
Which gives us:
$a is [(?^i:\b(hidden)\b)]
$a is defined
I found word: hidden Hidden hidden
But, honestly, I think pre-compiling the regex here is just over-complicating things. I'd write this code like this (removing the $a variable completely):
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $text = 'Try to find the hidden string here! Hidden or hidden';
if (my (#matched) = $text =~ /\b(hidden)\b/gi) {
print "I found word: #matched";
}
else {
print "No match, sorry.\n";
}

Perhaps you are looking for this piece of code
use strict;
use warnings;
use feature 'say';
my $text='Try to find the hidden string here! Hidden or hidden';
my $re = qr/(hidden)/i; # () capture found ignoring case
my #match = $text =~ /$re/g; # g specifies to look for all accurances
say for #match; # output each element of #match
Output
hidden
Hidden
hidden

Related

How to specify element in foreach loop to a variable?

I use below Perl code, and want to add specific $i in foreach into variable $targetBank and $targetEntry.
For 1_Target Bank & 1_Target Entry they are ok to print out.
But for 2_Target Bank & 2_Target Entry they are not working.
It seems the $targetBank and $targetEntry variable refresh every time in the foreach loop.
How should I modify my code?
my #SPLIT =split /\./, $longSentense;
foreach my $i (#SPLIT)
{
if($i =~ /u_b.*/)
{
my $targetBank=$i;
print "1_Target Bank= $targetBank\n";
}
elsif ($i =~ /g_tq.*/)
{
my $targetEntry=$i;
print "1_Target Entry= $targetEntry\n";
}
}
print "2_Target Bank= $targetBank\n";
print "2_Target Entry= $targetEntry\n";
First, always add use strict; use warnings; at the beginning of your scripts (more or that later).
A variable is only visible in the scope it was defined in. For instance, if you do:
{
my $var = 42;
print "1: $var\n"; # prints "1: 42"
}
print "2: $var\n"; # ERROR !!!
$var is visible inside the { ... } block, but not after. With use strict, the print "2: $var\n"; will not compile, because $var is not declared in this scope. Without use strict, this statement will work, but $var will be undefined.
To get this example to work, you need to declare $var in the same scope as print "2: $var\n":
my $var;
{
$var = 42;
print "1: $var\n"; # prints "1: 42"
}
print "2: $var\n"; # prints "2: 42", as expected.
Note how I wrote $var = 42 rather than my $var = 42: the later would declare a new variable (in this scope only), which would "shadow" the previous declaration, and, when exiting the scope (at }), the $var that would be visible would be the one declare before the block, which would still be undefined.
Also, the word "scope" is maybe a bit confusing. You can (mostly) think of a scope as "everything inside curly braces + the global scope": if () { new scope here }, for (...) { new scope here }, sub { new scope here }, and, everything that is not inside a block is in the global scope. Small subtlety: when you write if (my $var = ...) { ... } or for my $var (...) { ... }, it introduces 2 scopes: one with $var, and one inside the { ... } (and they are both closed at the end of the if/for). See this small tutorial about scopes.
Thus, your code should be:
use strict; # never omit
use warnings; # those 2 lines
my #SPLIT =split /\./, $longSentense;
my ($targetBank, $targetEntry); # Declaring your variables
foreach my $i (#SPLIT)
{
if($i =~ /u_b/)
{
$targetBank=$i;
print "1_Target Bank= $targetBank\n";
}
elsif ($i =~ /g_tq/)
{
$targetEntry=$i;
print "1_Target Entry= $targetEntry\n";
}
}
print "2_Target Bank= $targetBank\n";
print "2_Target Entry= $targetEntry\n";
Note that each time $targetBank=$i; is executed, the previous value of $targetBank is lost. If the condition if($i =~ /u_b/) is true only once in your loop, then this is not an issue. Otherwise, you might want to use an array instead of a scalar to store multiple values.
Also, as pointed out by #TLP, /u_b.*/ and /g_tq.*/ can be simplified to /u_b/ and /g_tq/.

Regular expression to validate an email in perl

I am new in Perl and trying to catch hold of the scripting language where I come across regular expression to validate a email address. I am sharing the perl script. I am not sure where I am making mistake in it. The \# part is omitted always following which the correct email id is also showing as invalid.
Here is the code :
#!/usrs/bin/perl/
$string = "XYZ#yahoo.com";
if ( $string =~ /([a-zA-Z]+)\#([a-zA-Z]+)\.(com|net|org)/)
{
print "TRUE";
print $string;
}
else
{
print "FALSE";
print $string;
}
Thanks for your help.
The regex for validating an email address is included in the source code for Email::Valid. I've copied it below:
$RFC822PAT = <<'EOF';
[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\
xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xf
f\n\015()]*)*\)[\040\t]*)*(?:(?:[^(\040)<>#,;:".\\\[\]\000-\037\x80-\x
ff]+(?![^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015
"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\
xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80
-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*
)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\
\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\
x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>#,;:".\\\[\]\000-\037\x8
0-\xff]+(?![^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n
\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x
80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^
\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040
\t]*)*)*#[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([
^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\
\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>#,;:".\\\[\]\000-\037\
x80-\xff]+(?![^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-
\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()
]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\
x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\04
0\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\
n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\
015()]*)*\)[\040\t]*)*(?:[^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff]+(?!
[^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\
]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\
x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\01
5()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*|(?:[^(\040)<>#,;:".
\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff]
)|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^
()<>#,;:".\\\[\]\x80-\xff\000-\010\012-\037]*(?:(?:\([^\\\x80-\xff\n\0
15()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][
^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)|"[^\\\x80-\xff\
n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^()<>#,;:".\\\[\]\
x80-\xff\000-\010\012-\037]*)*<[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?
:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-
\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:#[\040\t]*
(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015
()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()
]*)*\)[\040\t]*)*(?:[^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\0
40)<>#,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\
[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\
xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*
)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80
-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x
80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t
]*)*(?:[^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>#,;:".\\
\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])
*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x
80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80
-\xff\n\015()]*)*\)[\040\t]*)*)*(?:,[\040\t]*(?:\([^\\\x80-\xff\n\015(
)]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\
\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*#[\040\t
]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\0
15()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015
()]*)*\)[\040\t]*)*(?:[^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff]+(?![^(
\040)<>#,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|
\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80
-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()
]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x
80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^
\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040
\t]*)*(?:[^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>#,;:".
\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff
])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\
\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x
80-\xff\n\015()]*)*\)[\040\t]*)*)*)*:[\040\t]*(?:\([^\\\x80-\xff\n\015
()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\
\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)?(?:[^
(\040)<>#,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>#,;:".\\\[\]\000-
\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\
n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|
\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))
[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff
\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\x
ff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(
?:[^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>#,;:".\\\[\]\
000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\
xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\x
ff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)
*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*#[\040\t]*(?:\([^\\\x80-\x
ff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-
\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)
*(?:[^(\040)<>#,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>#,;:".\\\[\
]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\]
)[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-
\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\x
ff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(
?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80
-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<
>#,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>#,;:".\\\[\]\000-\037\x8
0-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:
\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]
*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)
*\)[\040\t]*)*)*>)
EOF
But your actual problem is this line:
$string = "XYZ#yahoo.com";
The #yahoo looks like an array variable to Perl, and and you don't have an array called #yahoo it gets replaced with an empty string. Try printing the value of $string to see what you get.
The solution is either to use single quotes (so the array variable isn't expanded):
$string = 'XYZ#yahoo.com';
Or to escape the # with a \:
$string = "XYZ\#yahoo.com";
Alway add use strict and use warnings to your Perl programs. They would have told you what the problem is.
#!/usr/bin/perl
use strict;
use warnings;
use Email::Valid;
my $email_address = 'a.n#example.com';
unless( Email::Valid->address($email_address) ) {
print "Sorry, that email address is not valid!";
}
Reference Site: http://learn.perl.org/examples/email_valid.html
For Regex Pattern try this:
my $pattern= '^([a-zA-Z][\w\_\.]{6,15})\#([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,4})$';
Reference Site: https://www.experts-exchange.com/articles/8652/Email-validation-using-Regular-Expression-in-Perl.html
Change your if condition to
if ($string =~ /^[a-z0-9A-Z][A-Za-z0-9.]+[A-Za-z0-9]\#[A-Za-z0-9.-]+$/)
and change
$string = "XYZ#yahoo.com"; to
$string = 'XYZ#yahoo.com';
Refference : http://perlmaven.com/email-validation-using-regular-expression-in-perl
for details.
Try
if ($email =~ /^[a-z0-9]([a-z0-9.]+[a-z0-9])?\#[a-z0-9.-]+$/)
And some test code:
#!/usr/bin/perl
my $email = "john.doe\#acme.org";
if ($email =~ /^[a-z0-9]([a-z0-9.]+[a-z0-9])?\#[a-z0-9.-]+$/) {
print "Valid email\n";
} else {
print "Not valid email\n";
}
exit;
Output:
Valid email

Case statement in perl: not able to enter proper case

#!/usr/bin/perl -w
use warnings;
use diagnostics;
use Switch;
open FH, "<$ARGV[0]" or die "$!";
sub commandType{
print "comm entered for $_";
switch($_){
case("add") {print "this is add\n"}
case("sub") {print "this is sub\n"}
case("neg") {print "this is neg\n"}
case("eq") {print "this is eq\n"}
case("gt") {print "this is gt\n"}
case("lt") {print "this is lt\n"}
case("and") {print "this is and\n"}
case("or") {print "this is or\n"}
case("not") {print "this is not\n"}
}
}
while(<FH>){
next if /^\s*\/\//;
next if /^\s*$/;
my $line = "$_";
$line =~ s/\s+$//;
print "$line\n";
commandType($line);
}
Here is my code which takes the input from the following file supplied to it through the command line:
// Pushes and adds two constants.
push constant 7
push constant 8
add
For each line of the file above the perl code will run the subroutine commandType to check if it is among the given cases inside the subroutine and prints if it is. But even though the add command is present in the file above the code still does not print it. I am getting the following output:
push constant 7
comm entered for push constant 7
push constant 8
comm entered for push constant 8
add
comm entered for add`
Why is case "add" not printing anything?
EXPLANATION
The problem is that $_ doesn't automatically refer to the first argument passed to a sub, currently you are reading the same $_ as the one in your while-loop.
The value of $_ when inside commandType is the line read, still having the potential new-line attached to it, and since "add\n" isn't equal to "add", your case isn't entered.
SOLUTION
It would be preferred to change the contents of sub commandType to the below:
sub commandType{
my $cmd = shift; # retrieve first argument
print "comm entered for $cmd";
switch($cmd) {
...
}
}
It isn't safe to use $_ as you would a normal variable. It has global scope and many built-in Perl operators act on it, so it is likely to be modified without any obvious reason.
In any case, the parameters passed to a subroutine are presented in #_, not in $_ and it is random chance that it seems to contain the right value in this case.
Rewrite your commandType subroutine like this and it should start behaving more sensibly
sub commandType {
my ($cmd) = #_;
print "comm entered for $cmd";
switch ($cmd) {
case 'add' { print "this is add\n" }
case 'sub' { print "this is sub\n" }
case 'neg' { print "this is neg\n" }
case 'eq' { print "this is eq\n" }
case 'gt' { print "this is gt\n" }
case 'lt' { print "this is lt\n" }
case 'and' { print "this is and\n" }
case 'or' { print "this is or\n" }
case 'not' { print "this is not\n" }
}
}
You must also always add use strict at the top of every program, especially if you are asking for help with it. It will quickly report trivial errors that you may otherwise spend valuable time tracking down.
The Switch module is also unsafe, and the built-in language construct given/when that has been available since version 10 has been marked as experimental because of a number of arcane shortcomings. You are much better off using a list of if statements as described in the "Basic BLOCKs" section of perlsyn.
Starting from Perl 5.10.1 (well, 5.10.0, but it didn't work right), you can say use feature "switch"; to enable an experimental switch feature. Under the "switch" feature, Perl gains the experimental keywords given , when , default , continue, and break.
#!/usr/bin/perl
use strict;
use warnings;
use feature "switch";
while(my $line=<DATA>){
given ($line) {
when (/push/) { print 'found push' }
when (/add/) { print 'found add' }
}
}
__DATA__
push constant 7
push constant 8
add
Demo
Also see: Perl 5.20 and the fate of smart matching and given-when?

Perl: How to detect which file exists among foo.(txt|abc)

My perl script needs to detect the extension of an existing file and print out the filename. The input that specifies the filename with a vague extension would be in this format:
foo.(txt|abc)
and the script would print "foo.txt" if it exists. If foo.txt does not exist and foo.abc exists, then it would print "foo.abc."
How can I do this detection and printing of the correct existing file in a neat and clean way?
Thanks!
Actually, you've almost got the regular expression right there: the only thing you need to do is escape the . with a backslash (since . means "any character except the newline character" in regular expressions), and it would also help to put a ?: inside of the parentheses (since you don't need to capture the file extension). Also, ^ and $ denote markers for the beginning and the end of the string (so we're matching the entire string, not just part of a string...that way we don't get a match for the file name "thisisnotfoo.txt")
Something like this should work:
use strict;
use warnings;
my $file1="foo.txt";
my $file2="foo.abc";
my $file3="some_other_file";
foreach ($file1,$file2,$file3)
{
if(/^foo\.(?:txt|abc)$/)
{
print "$_\n";
}
}
When the above code is run, the output is:
foo.txt
foo.abc
Take a look at perldoc perlretut for more stuff about regular expressions.
You may want to look at glob, but you'd have to use a different syntax. The equivalent would be:
foo.{txt,abc}
See File::Glob for more information. Also note that this will return a list of all of the matches, so you'll have to do your own rules if it should prefer one when multiple exist.
sub text_to_glob {
my ($s) = #_;
$s =~ s/([\\\[\]{}*?~\s])/\\$1/g;
return $s;
}
my $pat = 'foo.(txt|abc)';
my #possibilities;
if (my ($base, $alt) = $pat =~ /^(.*\.)\(([^()]*)\)\z/s) {
#possibilities = glob(
text_to_glob($base) .
'{' . join(',', split(/\|/, $alt)) . '}'
);
} else {
#possibilities = $pat;
}
for my $possibility (#possibilities) {
say "$possibility: ", -e $possibility ? "exists" : "doesn't exist";
}
glob, but also see File::Glob
-e
use strict;
use warnings;
FILE:
for (glob "file.{txt,abc}") {
if (-f $_) {
print $_, "\n";
last FILE;
}
}

Why won't my Perl function work?

I am having trouble with a function I wrote...
sub TemplateReplace
{
my($regex, $replacement, $text) = #_;
$text =~ s/($regex)/($replacement)/gs;
}
my $text = "This is a test.";
TemplateReplace("test", "banana", $text);
But it doesn't work. I thought arguments were sent by reference in Perl. Does the line my($regex, $replacement, $text) = #_; then copy them? How do I fix this?
sub TemplateReplace
{
my($regex, $replacement, $text) = #_;
$text =~ s/($regex)/($replacement)/gs;
return $text;
}
my $text = "This is a test.";
$text = TemplateReplace("test", "banana", $text);
There. That should work.
And yes, your my( ..) = #_ does copy the args. So if you're modifying a variable, you need to return it unless it's a global.
You are modifying a copy of the $text you passed in; this will have no effect on the original.
#!/usr/bin/perl
use strict;
use warnings;
my $text = "This is a test.";
template_replace(qr/test/, "bannana", $text);
print "$text\n";
sub template_replace {
my $regex = shift;
my $replacement = shift;
$_[0] =~ s/$regex/$replacement/gs;
}
The code above works because the elements of #_ are aliased to the variables passed in. But Adnan's answer is the more commonly done. Modifying arguments passed into functions is surprising behavior and makes things like template_replace(qr/foo/, "bar", "foo is foo") not work.
It's the "assignment" part of the sub-routine that is making the copies of the data.
If you modify the #_ arguments directly, they work as you expect. It is however, not very readable. :-)
use strict;
umask(0);
$|=1;
my $debug = 0;
my $text = "This is a test.";
print "Before 1: [$text]\n";
TemplateReplace("test", "banana", $text);
print "After 1: [$text]\n";
print "Before 2: [$text]\n";
TemplateReplace2("test", "banana", $text);
print "After 2: [$text]\n";
sub TemplateReplace
{
my ($regex, $replacement, $text) = #_;
$text =~ s/($regex)/($replacement)/gs;
}
sub TemplateReplace2
{
$_[2] =~ s/$_[0]/$_[1]/gs;
}
returns:
Before 1: [This is a test.]
After 1: [This is a test.]
Before 2: [This is a test.]
After 2: [This is a banana.]
Here is a variation on how to do it, which is almost identical to your code with a slight difference.
use strict;
use warnings;
sub TemplateReplace {
my($regex, $replacement, $text) = #_;
$$text =~ s/($regex)/$replacement/gs;
}
my $text = "This is a test.";
TemplateReplace("test", "banana", \$text);
print $text;
This behavior is explicit instead of implicit. In practice, it works identically to Chas. Owens result, but uses scalar-refs instead of relying on understanding the behaviour of arrays.
This will make it more obvious to anybody reading your code that the function "TemplateReplace" is intentionally modifying $text.
Additionally, it will tell you you're using it wrong by squawking with :
Can't use string ("This is a test.") as a SCALAR ref while "strict refs" in use at replace.pl line 9.
If you happen to forget the \ somewhere.