# Macro for replacing matching tokens in a parameter?

I would like to have a macro, call it \magicreplace which gets some arbitrary parameter (= sequence of tokens) and replaces every occurrence of some token (say, a or x or ,) with some fixed sequence of tokens (say hello, or \text{hello}).

So, \magicreplace{a}{abc{abc}} expands to hellobc{abc}.

Is there something available in some package for doing that? If not, how would I go about implementing this thing?

Notes:

• Can be LaTeX rather than plain TeX
• pdftex and/or xetex please
• since you use \rm I'm assuming you need this for plain tex not latex? Also do you need it for pdftex or would luatex or xetex solutions be OK? – David Carlisle Jun 30 '17 at 20:54
• if you are replacing a by hello what do you want abc{abc} to produce? (hellobc{abc} is perhaps easier than {hellbc{hellobc}) – David Carlisle Jun 30 '17 at 20:57
• @DavidCarlisle: See edits. – einpoklum Jun 30 '17 at 21:08

This is already available out of the box in expl3:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\magicreplace}{mmm}
{
\tl_set:Nn \l_einpoklum_magicreplace_tl { #3 }
\tl_replace_all:Nnn \l_einpoklum_magicreplace_tl { #1 } { #2 }
\tl_use:N \l_einpoklum_magicreplace_tl
}
\tl_new:N \l_einpoklum_magicreplace_tl
\ExplSyntaxOff

\begin{document}

\magicreplace{a}{hello}{abc{abc}}

\magicreplace{a}{hello}{a b c{a b c}a}

\end{document}


A different version where the replacement string is fixed (but changeable).

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\magicreplace}{mm}
{
\tl_set:Nn \l_einpoklum_magicreplace_tl { #2 }
\tl_replace_all:NnV \l_einpoklum_magicreplace_tl { #1 } \l_einpoklum_magicreplace_rep_tl
\tl_use:N \l_einpoklum_magicreplace_tl
}
\NewDocumentCommand{\setreplacement}{m}
{
\tl_set:Nn \l_einpoklum_magicreplace_rep_tl { #1 }
}

\tl_new:N \l_einpoklum_magicreplace_tl
\tl_new:N \l_einpoklum_magicreplace_rep_tl
\cs_generate_variant:Nn \tl_replace_all:Nnn { NnV }
\ExplSyntaxOff

\begin{document}

\setreplacement{hello}

\magicreplace{a}{hello}{abc{abc}}

\setreplacement{world}
\magicreplace{a}{a b c{a b c}a}

\end{document}


• where's the fun in stealing from boxes? – David Carlisle Jun 30 '17 at 22:12
• @DavidCarlisle That Bruno does the work. – egreg Jun 30 '17 at 22:17
• I suspected there was something like this deep under the hood. – einpoklum Jul 1 '17 at 9:38

It's possible to take more care over white space but a simple version is

\documentclass{article}

\def\zz#1#2#3{\def\zzz##1#1{##1#2\zzz}{\zzz#3\zzzz#1\relax}}
\def\zzzz#1\relax{}
\begin{document}

\zz{a}{hello}{abc{abc}abc}
\end{document}

• What would the issue with whitespace be? – einpoklum Jun 30 '17 at 21:51
• @einpoklume actually with that form space is probably Ok but if the list of tokens before the a is just a brace group, th ebraces would be dropped – David Carlisle Jun 30 '17 at 22:15