blueFish
blueFish

Reputation: 79

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";

Upvotes: 0

Views: 86

Answers (1)

Dada
Dada

Reputation: 6626

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/.

Upvotes: 1

Related Questions