What my dog really hears
**REXX 151 148 141 bytes **
(Kinda seemed appropriate)
i=arg(1)
m=i
o=translate(m,'',xrange('A','z'),'*')
p=0
do forever
p=pos('REX',m,p+1)
if p=0 then leave
o=overlay(substr(i,p,3),o,p)
end
say o
Try it here
Notes for non-REXXers:
- translate is a character replacement function (name comes from an assembler instruction on IBM MF). It searches string1 for the characters in string3. Every time it finds one it replaces it with the same positioned one in string2. If string2 is too short it is padded with the pad character.
See here for translate function
- overlay simply overlays the string1 on top of string2 at the specified position.
See here for overlay function
Retina, 24 21 bytes
i`(rex)|(\w)
$1$#2$**
Try it online!
Explanation
Skipping rex
s is easiest by matching them as well, because matches can't overlap. So if we give priority to rex
over other letters, those will be covered in a single match and not touched by the individual-letter matches.
But how do we do different things depending on the alternative that was used for the match? Unfortunately, Retina doesn't (yet) have any conditional substitution syntax like the Boost regex flavour. But we can fake it by including both substitutions in a single replacement and making sure that only one of them is non-empty:
$1
is the first capturing group, i.e. the(rex)
. If we did matchrex
this simply writes it back (so it does nothing), but if we didn't matchrex
then$1
is an empty string and vanishes.$#2$**
should be read as($#2)$*(*)
.$#2
is the number of times group2
was used, i.e. the(\w)
. If we matchedrex
this is0
, but if we matched any other individual letter, this is1
.$*
repeats the next character as many times as its left-hand operand. So this part inserts a single*
for individual-letter matches and nothing at all forrex
.
JavaScript (ES6), 42 41 38 bytes
s=>s.replace(/rex|\w/gi,m=>m[1]?m:"*")
Try It
o.innerText=(f=
s=>s.replace(/rex|\w/gi,m=>m[1]?m:"*")
)(i.value="Rex, I told you not to do this! You're making me angry Rex!")
oninput=_=>o.innerText=f(i.value)
<input id=i><pre id=o>
Explanation
s=> :Anonymous function that takes the string as an argument via parameter s.
s.replace(x,y) :Replace x in s with y.
/rex|\w/gi :Case-insenstive regular expression that globally matches all occurrences
of "rex" or any single letter, number or underscore.
(numbers & underscores will never be included in the input.)
m=> :Anonymous function that takes each match as an argument via parameter m.
m[1]? :If string m has a second character, ...
(Equivalent to m.charAt(1))
m :Return m, ...
:"*" :Otherwise return "*".