Regex- replace sequence of one character with same number of another character

I was also looking for a pure regex solution for something like this. I didn't find one on SO, so I worked it out.

Short version: here is the regex:

((?<====)=)|(=(?====))|((?<===)=(?==))|((?<==)=(?===))

Here is how I got there, using R:

str <- " = == === ==== ===== ====== ======="

gsub("=(?====)",      "-", str, perl = TRUE) # (1) Pos. lookahead
gsub("(?<====)=",     "-", str, perl = TRUE) # (2) Pos. look-behing
gsub("(?<===)=(?==)", "-", str, perl = TRUE) # (3) Middle part for cases of 4 or 5 ='s (1/2)
gsub("(?<==)=(?===)", "-", str, perl = TRUE) # (4) Middle part for cases of 4 or 5 ='s (2/2)

# Combining all, we have:
gsub("((?<====)=)|(=(?====))|((?<===)=(?==))|((?<==)=(?===))", "-", str, perl = TRUE) # (5)

(1) = == === -=== --=== ---=== ----===
(2) = == === ===- ===-- ===--- ===----
(3) = == === ==-= ==--= ==---= ==----=
(4) = == === =-== =--== =---== =----==
(5) = == === ---- ----- ------ -------

Alternative method for a less convoluted regex (but requires 3 steps)

# First, deal with 4 & 5 equal signs with negative look-behind and lookahead
str <- gsub("(?<!=)={4}(?!=)", "----",     str, perl = TRUE) # (2.1)
str <- gsub("(?<!=)={5}(?!=)", "-----",    str, perl = TRUE) # (2.2)

# Then use regex (3) from above for 6+ equal signs
str <- gsub("((?<====)=)|(=(?====))", "-", str, perl = TRUE) # (2.3)

(2.1) = == === ---- ===== ====== =======
(2.2) = == === ---- ----- ====== =======
(2.3) = == === ---- ----- ------ -------

It's possible with Perl:

my $string = "===== Hello World ====";
$string =~ s/(====+)/"-" x length($1)/eg;
# $string contains ----- Hello World ----

Flag /e makes Perl execute expression in second part of s///. You may try this with oneliner:

perl -e '$ARGV[0] =~ s/(====+)/"-" x length($1)/eg; print $ARGV[0]' "===== Hello World ===="

Depending what language you're using. Basically, in some languages, you can put code in the right side of the regexp, allowing you to do something like this: (this is in perl):

s/(=+)/(length($1) > 3 ? "-" : "=") x length($1)/e

The 'e' flag tells perl to execute the code in the right side of the expression instead of just parsing it as a string.

Tags:

Regex

Replace