Quoth yjnnhauhht said:
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][
[:]][4][[c]]
[1]a[w[]][23][b[:][]][4][c[]]