search/replace values from an array...

S

Sandman

Ok, so here is a snippet that shows what I want to do:

#!/usr/bin/perl
use strict;
use warnings;

my $string = "Hello World!";

my %array = (
"Hello (.*?)!", "Goodbye, little #1#!"
# search replace
);
foreach (keys %array){
if ($string=~m/$_/i){
# It matched!
$array{$_}=~s/#(\d+)#/$$1/;
# replace #1# with $1, #2# with $2...
$string=~s/$_/$array{$_}/g;
# replace the string;
}
}

print $string;



The wanted result is "Goodbye, little World!", fetching "World" from $1 of the
match 4 lines up, but the error message is

File "test.pl"; Line 14: Can't use string ("1") as a SCALAR ref
while "strict refs" in use

So how do I solve it?
 
N

nyana

I thought scalars that started with a number had to take numbers. Is your
scalar taking text? Then it should start with a letter.

"Variable names that begin with a digit can contain only digits, and
variable names that begin with a character other than an alphanumeric or
underscore can contain only that character." -- Perl in a Nutshell,
Patwardwan et al.
 
A

Anno Siegel

Sandman said:
Ok, so here is a snippet that shows what I want to do:

#!/usr/bin/perl
use strict;
use warnings;

my $string = "Hello World!";

my %array = (
"Hello (.*?)!", "Goodbye, little #1#!"
# search replace
);
foreach (keys %array){
if ($string=~m/$_/i){
# It matched!
$array{$_}=~s/#(\d+)#/$$1/;
^^
Is this line 14? "$$1" is a scalar dereference that would fail with
something like your message below.

Also, you're changing the association of pattern and replacement in %array
here. That is not something you want to do, except if you plan to
use %array only once.
# replace #1# with $1, #2# with $2...
$string=~s/$_/$array{$_}/g;
# replace the string;
}
}

print $string;



The wanted result is "Goodbye, little World!", fetching "World" from $1 of the
match 4 lines up, but the error message is

File "test.pl"; Line 14: Can't use string ("1") as a SCALAR ref
while "strict refs" in use

So how do I solve it?

Here is one way. When you check each regex, build the replacement string
from the subpatterns that are captured by the regex. You do this by
(globally) replacing the markers "#1#", "#2#", etc. with the corresponding
submatch. The replacement string is now ready to use in a simple
substitution. For instance:

my %tab = (
'Hello (.*?)!' => 'Goodbye, little #1#...',
'Welcome (.*?) and (.*?)!' => 'Farewell, honorable #2# and fair #1#!',
);

for ( "Welcome ladies and gentlemen!", "Hello World!" ) {
my $string = $_; # make a copy we can change

while ( my ( $search, $replace) = each %tab ) {
# build ready-to-use replacement string from template
my $n = 1; # submatch number
for ( $string =~ /$search/ ) { # loop over submatches
$replace =~ s/#$n#/$_/g, # substitute one submatch everywhere
$n ++; # next submatch
}
last if $string =~ s/$search/$replace/;
}
print "$string\n";

}

The "last" in the while-loop ensures that at most one replacement is
done. Since you are using a hash, the replacements are tried in a random
sequence. It wouldn't make sense to try re-replacement on an already
processed string unless you control the order of the tries.

Anno
 
M

Matt Garrish

nyana said:
I thought scalars that started with a number had to take numbers. Is your
scalar taking text? Then it should start with a letter.

"Variable names that begin with a digit can contain only digits, and
variable names that begin with a character other than an alphanumeric or
underscore can contain only that character." -- Perl in a Nutshell,
Patwardwan et al.

I have to believe you've taken that completely out of context. Not having
the book, I refer you to the perldata perldoc:

<quote>
Names that start with a digit may contain only more digits. Names that do
not start with a letter, underscore, digit or a caret (i.e. a control
character) are limited to one character, e.g., $% or $$. (Most of these one
character names have a predefined significance to Perl. For instance, $$ is
the current process id.)
</quote>

The variables $1, $2 ... are special match variables (i.e., they contain the
text matched by a regex). You cannot create variable names that begin with a
digit for this reason, and variables that begin with a digit can only
contain more digits (for example, $4323 would contain the text matched in
the four-thousand-three-hundered-and-twenty-third set of parens, regardless
of how hideous a regex that might be : ). You seem to be mistaking Perl for
a strongly typed language, which it's not. $1 can contain the string 'Hello
World' just as easily as $var can contain the numeric value 12.

I would suggest you reread the perldocs, starting with perldata and moving
on to perlre and perlvar.

Matt
 
P

Paul Lalli

I thought scalars that started with a number had to take numbers. Is your
scalar taking text? Then it should start with a letter.

"Variable names that begin with a digit can contain only digits, and
variable names that begin with a character other than an alphanumeric or
underscore can contain only that character." -- Perl in a Nutshell,
Patwardwan et al.

You've misparsed this paragraph. It does not say that variables whose
names start with digits can contain only digits, etc. It says that
variable NAMES that start with digits can contain only digits. The
contents of the variable has nothing at all to do with the name of the
variable.

Paul Lalli
 
E

Eric Bohlman

"Or else it doesn't, you know. The name of the song is called
'Haddock's Eyes' ."

"Oh, that's the name of the song, is it?" Alice said, trying to feel
interested.

"No, you don't understand," the Knight said, looking a little vexed.
"That's what the name is called . The name really is 'The Aged Aged
Man' ."

"Then I ought to have said 'That's what the song is called?'" Alice
corrected herself.

"No, you oughtn't: that's quite another thing! The song is called
'Ways and Means' : but that's only what it's called , you know!"

"Well, what is the song, then?" said Alice, who was by this time
completely bewildered.

"I was coming to that," the Knight said. "The song really is
'A-sitting on a Gate' : and the tune's my own invention."

I don't think you can fully appreciate this in all its profundity unless
you have an assembler background.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top