From: Ben Morrow on

Quoth yjnnhauhht <yjnnhauhht(a)mailinator.com>:
> On Jul 2, 2:00�am, s...(a)netherlands.com wrote:
> > On Thu, 01 Jul 2010 16:47:51 -0700, s...(a)netherlands.com wrote:
> > >Or you can combine it all in a double eval regex as something like this:
> > >(expanded with print for detail)
> >
> > >$i = 2;
> > >$string =~ s/(test)(string)/print '${'.$i."}\n"; '${'.$i.'}'/ee;
> > ># or, shortened
> > ># $string =~ s/(test)(string)/'$'.$i/ee;
> >
> > Or, another popular notation:
> >
> > $string =~ s/(test)(string)/"\$$i"/ee;
>
> Thanks!
> This answer my needs.

BE CAREFUL. /ee does a string eval, so if (as I suspect) your $i is
actually coming from user input, you must validate it carefully.

Consider $i = '{system("rm -rf /")}', for instance.

Ben

From: Ben Morrow on

Quoth yjnnhauhht <yjnnhauhht(a)mailinator.com>:
> On Jul 2, 3:39�pm, yjnnhauhht <yjnnhau...(a)mailinator.com> wrote:
> > On Jul 2, 12:23�am, Big and Blue <N...(a)dsl.pipex.com> wrote:
> > > On 07/01/10 17:29, Tad McClellan wrote:
> >
> > > > � � �$string=~s/(test)/test/;
> >
> > > > I smell an XY-problem.
> >
> > > > What is it that you are actually trying to accomplish?
> >
> > > Is it, by chance:
> >
> > > my $i=1;
> > > my $string="teststring";
> > > $string=~s/(?<test>test)/$+{test}/;
> > > print "$string\n";
> >
> > This doesn't solve my issue, cause I need to do the thing in a for
> > loop where the $i is incremented.
> > Thanks for your time though.
>
> Well what I really want to do is some kind of "highlighting grep -E"
> which highlights the part of the match pattern that is inside ().
> For example if I do mygrep "...\w*(test)..." file, I get the lines
> matching the pattern and the word test is highlighted.
> To do this I have to add a highligth/nohighligth control string before
> and after each () group.
> I though I will be able to do this in one regex, but failed and only
> found a solution where I need to iterate on the () groups and do the
> s/.../$i/ I ask you about.

Well, now that you've *said* so...

my $str = "1a:23b:4c";

while ($str =~ /(\d+)(\w+)/g) {
my $added = 0;
for (1..$#+) {
substr $str, $-[$_] + $added, 0, "[";
$added++;
substr $str, $+[$_] + $added, 0, "]";
$added++;
}
pos($str) = $+[-1] + $added;
}

Ben

From: C.DeRykus on
On Jul 2, 6:51 am, yjnnhauhht <yjnnhau...(a)mailinator.com> wrote:
> On Jul 2, 3:39 pm, yjnnhauhht <yjnnhau...(a)mailinator.com> wrote:
>
>
>
> > On Jul 2, 12:23 am, Big and Blue <N...(a)dsl.pipex.com> wrote:
>
> > > On 07/01/10 17:29, Tad McClellan wrote:
>
> > > >      $string=~s/(test)/test/;
>
> > > > I smell an XY-problem.
>
> > > > What is it that you are actually trying to accomplish?
>
> > > Is it, by chance:
>
> > > my $i=1;
> > > my $string="teststring";
> > > $string=~s/(?<test>test)/$+{test}/;
> > > print "$string\n";
>
> > > ?
>
> > > --
> > >               Just because I've written it doesn't mean that
> > >                    either you or I have to believe it.
>
> > This doesn't solve my issue, cause I need to do the thing in a for
> > loop where the $i is incremented.
> > Thanks for your time though.
>
> Well what I really want to do is some kind of "highlighting grep -E"
> which highlights the part of the match pattern that is inside ().
> For example if I do mygrep "...\w*(test)..." file, I get the lines
> matching the pattern and the word test is highlighted.
> To do this I have to add a highligth/nohighligth control string before
> and after each () group.
> I though I will be able to do this in one regex, but failed and only
> found a solution where I need to iterate on the () groups and do the
> s/.../$i/ I ask you about.

my $str = "1a:23b:4c";

$str = s{ (\d+)(\w+) }
{ my $s;$s .= qq{[$_]} for $1,$2;$s }gex;

--
Charles DeRykus
From: C.DeRykus on
On Jul 4, 8:36 pm, "C.DeRykus" <dery...(a)gmail.com> wrote:
....
> my $str =  "1a:23b:4c";
>
> $str = s{ (\d+)(\w+) }
{...
^^^^^^^^^
$str =~

--
Charles DeRykus
From: sln on
On Fri, 2 Jul 2010 23:31:15 +0100, Ben Morrow <ben(a)morrow.me.uk> wrote:

>
>Quoth yjnnhauhht <yjnnhauhht(a)mailinator.com>:
>> On Jul 2, 3:390m, yjnnhauhht <yjnnhau...(a)mailinator.com> wrote:
>> > On Jul 2, 12:23!m, Big and Blue <N...(a)dsl.pipex.com> wrote:
>> > > On 07/01/10 17:29, Tad McClellan wrote:
>> >
>> > > > $string=~s/(test)/test/;
>> >
>> > > > I smell an XY-problem.
>> >
>> > > > What is it that you are actually trying to accomplish?
>> >
>> > > Is it, by chance:
>> >
>> > > my $i=1;
>> > > my $string="teststring";
>> > > $string=~s/(?<test>test)/$+{test}/;
>> > > print "$string\n";
>> >
>> > This doesn't solve my issue, cause I need to do the thing in a for
>> > loop where the $i is incremented.
>> > Thanks for your time though.
>>
>> Well what I really want to do is some kind of "highlighting grep -E"
>> which highlights the part of the match pattern that is inside ().
>> For example if I do mygrep "...\w*(test)..." file, I get the lines
>> matching the pattern and the word test is highlighted.
>> To do this I have to add a highligth/nohighligth control string before
>> and after each () group.
>> I though I will be able to do this in one regex, but failed and only
>> found a solution where I need to iterate on the () groups and do the
>> s/.../$i/ I ask you about.
>
>Well, now that you've *said* so...
>
> my $str = "1a:23b:4c";
>
> while ($str =~ /(\d+)(\w+)/g) {
> my $added = 0;
> for (1..$#+) {
> substr $str, $-[$_] + $added, 0, "[";
> $added++;
> substr $str, $+[$_] + $added, 0, "]";
> $added++;
> }
> pos($str) = $+[-1] + $added;
> }
>
>Ben

This approach is too simple. It won't handle nested groups;
/((\d+)(\w+))/ for example.

Then again, a more complex method that handles nesting
runs up against the indeterminate configuration;
'asdf' =~ /((X?))asdf/
'asdf' =~ /(X?)(Y?)asdf/
prodcing:
@- 0 0 0 0
@+ 4 0 0 4
The solution is to exclude empty capture groups.

I'd be curious if anyone else knows a simpler workable method other
than the below code (that works on nested groups).

-sln

---------------------------
use strict;
use warnings;

#
# This works for nested groups (but too complex)
#
my $str = "1aw23b:4c";

while ($str =~ /(\d+)[a-z]*(([a-z])(:?))/g)
{
my $newpos = pos($str);
my @B = @-;
my @E = @+;
my $numgrps = $#B;

for my $grp (1 .. $numgrps)
{
next if ($B[$grp] == $E[$grp]);
my $i;
##
my $curBpos = $B[$grp];
substr $str, $curBpos, 0, '[';
for $i ($grp .. $numgrps) {
++$B[$i] if ( $B[$i] >= $curBpos );
}
for $i ($grp .. $numgrps) {
++$E[$i] if ( $E[$i] >= $curBpos );
}
##
my $curEpos = $E[$grp];
substr $str, $curEpos, 0, ']';
for $i ($grp .. $numgrps) {
++$B[$i] if ( $B[$i] >= $curEpos );
}
for $i ($grp .. $numgrps) {
++$E[$i] if ( $E[$i] >= $curEpos );
}
$newpos += 2;
}
pos($str) = $newpos;
}

print $str,"\n";

#
# This does NOT work for nested groups (too simple)
#
$str = "1aw23b:4c";

while ($str =~ /(\d+)[a-z]*(([a-z])(:?))/g) {
my $added = 0;
for (1..$#+) {
next if ($-[$_] == $+[$_]);
substr $str, $-[$_] + $added, 0, "[";
$added++;
substr $str, $+[$_] + $added, 0, "]";
$added++;
}
pos($str) = $+[-1] + $added;
}
print $str,"\n";

__END__


[1]a[[w]][23][[b][:]][4][[c]]
[1]a[w[]][23][b[:][]][4][c[]]