Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make this nested loop continue in perl?

Tags:

hash

perl

Here is my code:

#!perl -w
use strict;

my %hash = (
    1 => "a",
    2 => "b",
);

foreach my $num ( keys %hash ) {
    while (<DATA>) {
        s/$num/$hash{$num}/g;
        print;
    }
}
__DATA__
121212
11111
222 

I intend to replace all numbers with the corresponding values that exists in hash. But it outputs:

a2a2a2
aaaaa
222
Hit any key to close this window...

Why is the foreach loop run once only? Who can explain it for me? And how should I change the code? I want it to output:

ababab
aaaaa
bbb

Thanks in advance.

like image 841
niejieqiang Avatar asked May 27 '26 15:05

niejieqiang


2 Answers

The reason the foreach loop appears to run only once is because you're reading from <DATA> one line at a time. The second time you loop through the outer loop, there's no more data left to read from data in your inner loop. Instead why don't you read all the <DATA> into a list first:

@mylist = <DATA>

And then loop over this list in your inner loop.

like image 147
Benj Avatar answered May 30 '26 09:05

Benj


Instead of looping through the file for each key in the hash, or slurping the file, you can combine the keys of the hash into one search pattern.

Note that in the current version of your script as well as in @Benj's answer, the order in which the substitutions are applied is indeterminate in that the ordering of keys returned by keys can differ across perls or even across different runs using the same perl.

Which means you should pick an ordering, and stick with it unless you like surprises. The following script combines both ideas. I decided to put longer keys before shorter ones which makes sense in most contexts.

#!perl -w
use strict;

my %hash = qw(1 a 11 zz 2 b);

my $pat = join '|', 
          map qr/\Q$_\E/, 
          sort { length $b <=> length $a }
          keys %hash
          ;

while (<DATA>) {
    s/($pat)/$hash{$1}/g;
    print;
}

__DATA__
121212
11111
222 

Output:

ababab
zzzza
bbb
like image 31
Sinan Ünür Avatar answered May 30 '26 08:05

Sinan Ünür



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!