Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Regular Expressions as variables. Simple code included 1

Status
Not open for further replies.

SparceMatrix

Technical User
Mar 9, 2006
62
0
0
US
I am trying to apply arrays in creating sequences of global Search and Replace Regular Expressions. I have the PERL Bookshelf CD 4.0 and have looked at the discussion in Chapter 7 on using the "qr// operator. But I have yet to apply a successful strategy using the substitution method I demonstrate below.

Here is the simple result that I am trying to achieve. The example is strictly an exercise and is not expected to make sense except as an abstraction of the problem.

Code:
#!/usr/bin/perl

use strict;
use warnings;

my $MyString = "1 The\n2 quick\n3 brown\n4 fox\n5 jumps\n6 over\n7 the\n8 lazy\n9 dog.";
print $MyString;
print "\n\n";

# Uncomment the print statements below to see the different steps.

$MyString =~ s/(t.+)/$1-$1/gi;
# print $MyString;
# print "\n\n";

$MyString =~ s/\n?\d\s/ /g;
# print $MyString;
# print "\n\n";

$MyString =~ s/(quick)/$1est/g;
print $MyString;
print "\n\n";

Now here I apply arrays to sort out the various steps in the Regular Expressions. I want it to work exactly the way the above code does, but this is as close as I've gotten.

Code:
#!/usr/bin/perl

#use strict;
#use warnings;

my $MyString = "1 The\n2 quick\n3 brown\n4 fox\n5 jumps\n6 over\n7 the\n8 lazy\n9 dog.";

$MySub[0][0] = qr/(t.+)/;
$MySub[1][0] = qr/\n?\d\s/;
$MySub[2][0] = qr/(quick)/;

$MySub[0][1] = "$1-$1";
$MySub[1][1] = " ";
$MySub[2][1] = "$1est";

foreach my $Search (@MySub) {

	$MyString =~ s/@$Search[0]/@$Search[1]/g;
	# Uncomment the print statements below to see the different steps.
	# print $MyString;
	# print "\n\n";
	}

print $MyString;
print "\n\n";

In assigning the strings to the array to be used later as regular expressions, I made progress when I started applying the "qr//" operator. But it remains that I cannot manage to apply the $1 variable. It seems like there should be a way to do this.

Any and all tips or clues would be appreciated. Some references would help.
 
Bad: $MySub[0][1] = "$1-$1";

Note that you are interpolating the $1 variable in this assignment. You want single quote so that it isn't interpolated.

Bad: $MyString =~ s/(quick)/$1est/g;

This could easily be misinterpreted as the variable "$1est" instead of "$1". Explicitly specify this by "${1}".

The problem with your code was in in what you were replacing. I was able to fix this with some creative use of evals. Unfortunately, the /i indicate stopped working in the process, so I fixed this by changing the first regex to [tT]. Otherwise, I leave it to you to figure out how this works.

Code:
#!/usr/bin/perl

#use strict;
#use warnings;

$MyString = "1 The\n2 quick\n3 brown\n4 fox\n5 jumps\n6 over\n7 the\n8 lazy\n9 dog.";

my @MySub;
$MySub[0][0] = qr/([tT].+)/;
$MySub[1][0] = qr/\n?\d\s/;
$MySub[2][0] = qr/(quick)/;

$MySub[0][1] = '$1-$1';
$MySub[1][1] = ' ';
$MySub[2][1] = '${1}est';

foreach my $Search (@MySub) {
	[COLOR=green]$MyString =~ s{$Search->[0]}{"\"$Search->[1]\""}eegi;[/color]
	
	# Uncomment this instead to see what is happening.
	#my $str; my $result;
    #$MyString =~ s{$Search->[0]}{
	#	$str = "$Search->[1]";
	#	print "String = '$str'";
	#	my $result = eval "\"$str\"";
	#	print " to '$result'\n";
	#	$result
	#}egi;

    # Uncomment the print statements below to see the different steps.
    #print $MyString;
    #print "\n\n";
}

print $MyString;
print "\n\n";

1;
 
Isn't it true that the use of "{}" brackets mean that the second part of the s{}{} is actually interpreted as PERL code? how does that effect your solution?

I'll try this tomorrow and get back.
 
No, that isn't true.

It's just a different delimiter. I prefer to use it because we are already trained to look for balanced brackets.

These are equivalent:
Code:
$MyString =~ s{$Search->[0]}{"\"$Search->[1]\""}eegi;
$MyString =~ s/$Search->[0]/"\"$Search->[1]\""/eegi;
 
Thanks for that solution. It works for me too.

Here is the source of my confusion regarding the delimiters. I misread this. The second delimited group is always interpreted differently than the first and if the /e modifier is used than the second part is interpreted as script irregardless of the delimiter.

Take care to separate in your mind the regex and replacement operands. The regex operand is parsed in a special regex-specific way, with its own set of special delimiters. The replacement operand is parsed and evaluated as a normal double-quoted string. The evaluation happens after the match (and with /g, after each match), so $1 and the like are available to refer to the proper match slice. There are two situations where the replacement operand is not parsed as a double-quoted string:
[ul][li]When the replacement operand's delimiters are single quotes, it is parsed as a single-quoted string, which means that no variable interpolation is done.[/li]
[li]If the /e modifier (discussed in the next section) is used, the replacement operand is parsed like a little Perl script instead of like a double-quoted string.[/li][/ul]
The little Perl script is executed after each match, with its result being used as the replacement.
 
Nice Job.

I appreciate the fact that you actually tracked down and sited the exact documentation that was the source of your confusion. SparceMatrix++

PS. I still feel like the code that I used to allow for the caching of the replacment strings was very hackish. Nevertheless, you stated at first that this was a learning exercise, so functioning code is all that is important.
 
Well, to be precise, this code is being put to practical purposes. The example is an exercise. But I haven't the slightest idea what you are talking about when you refer to "caching" in the above code. It is enough for my purposes that the code works at all. Thanks again.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top