5

This question is related to Carry out substring replacement on variable's contents. Is it possible to perform string replace on an arbitrary string, without expansion? MWE:

\documentclass{article}
\usepackage{xstring}
\begin{document}
\noexpandarg
\StrSubstitute{John \textit{knows} that Mary is a unicorn}{knows}{believes}
\end{document}

With this MWE, nothing is replaced. Desired behaviour is a replacement of \textit{knows} with \textit{believes}, i.e., verbatim, plain replacement. Also, e.g., \StrSubstitute{\textit{knows}}{tex}{latex} should result in \latexit{knows} (i.e., replacement should consider the string as given, without taking any internal semantics into consideration).

A pdflatex solution is preferred (no lua, perl, sed, text editor search and replace). xstring is not required.

Marijn
  • 37,699

2 Answers2

9

By default xstring doesn't look into groups. But you can force it to consider also the text in braces:

\documentclass{article}
\usepackage{xstring}
\begin{document}
\noexpandarg
\StrSubstitute{John {knows} that Mary is a unicorn}{knows}{believes}

\exploregroups
\StrSubstitute{John {knows} that Mary is a unicorn}{knows}{believes}

\StrSubstitute{John \textit{knows} that Mary is a unicorn}{knows}{believes}
\end{document} 

enter image description here

Ulrike Fischer
  • 327,261
2

Such a simple substitution can be obtained quite easily with l3regex.

\documentclass{article}
\usepackage{xparse,l3regex}

\ExplSyntaxOn
\NewDocumentCommand{\strsubstitute}{ +m m m }
 {
  \tl_set:Nn \l_marijn_strsubst_tl { #1 }
  \regex_replace_all:nnN { #2 } { #3 } \l_marijn_strsubst_tl
  \tl_use:N \l_marijn_strsubst_tl
 }
\tl_new:N \l_marijn_strsubst_tl
\ExplSyntaxOff

\begin{document}

\strsubstitute{John \textit{knows} that Mary is a unicorn}{knows}{believes}

\strsubstitute{John \textit{knows} that Mary is a unicorn}{\c{textit}}{\c{textbf}}

\end{document}

enter image description here

egreg
  • 1,121,712