and @+. These represent the offsets in the string where a capture group begins and ends. The $1 group starts at $-[1] and ends just before $+[1], so the length of $1 is $+[1]-$-[1]. If this sort of punctuation overload makes you twitchy, you can make it more readable by adding use English; and substituting Cobol-level verbosity: $LAST_MATCH_END[1]-$LAST_MATCH_START[1].
So what we want to do during the substitution is evaluate a little bit of code:
my $n = $LAST_MATCH_END[1] - $LAST_MATCH_START[1];
( $n > 1 : $n : "" ) . $2
We can do that in Perl. Adding the /e flag to the substitution operator lets us put code in the replacement.
s/.../my $n=$+[1]-$-[1];($n>1?$n:"").$2/e
Two more flags will reduce the problem to a one-liner. We want to do this globally, so we need /g, of course. And we want the result of the substitution as an output value. Normally the s/// operator returns the number of substitutions; to yield the modified string use the /r flag.
The final, dense code looks like:
sub rleRE($str)
{
return ( $str =~ s/((.)\2*)/my $n=$+[1]-$-[1];($n>1?$n:"").$2/ger );
}
What about the decoding bonus? Even easier with regular expressions. We can exploit the /e flag again. Everywhere that we find the pattern of a number followed by a character, replace it with the replicated character.
sub rle_dec_RE($str)
{
return $str =~ s/(\d+)(.)/$2x$1/ger;
}
The breakdown:
/(\d+)(.)/-- Capture an integer ($1) and the character following it ($2).
/$2x$1/-- This is code, not a string. Thexis the Perl replication operator.
s///ger-- As before, we want to do this globally (g), using expression evaluation in the replacement (e), and returning the modified string (r).
SOCIAL SHARE CARD GENERATOR