19

I'd like to write something like this:

\replace{Text should be replaced here, here and here}{here}{Latex}

It should output

Text should be replaced Latex, Latex and Latex

How can this be done?

10
  • 1
    Welcome to TeX.SX! What about there? Should here be replaced too, to give tLatex? – egreg Nov 25 '14 at 16:19
  • There are probably more than one approach for this. – user31729 Nov 25 '14 at 16:22
  • @egreg In my case I will be replacing a keyword that doesn't occur in arbitrary text, so it doesn't matter. – Marian Nov 25 '14 at 16:22
  • @egreg Updated the question. I'm looking for a way to replace 'eqn' and 'eqn.' (and 'eqn,') – Marian Nov 25 '14 at 17:29
  • 1
    @Marian You may ask a new question about your real problem; I believe there are better ways to deal with it. – egreg Nov 25 '14 at 20:57
19
+50

A complex solution that only replaces complete words:

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

\ExplSyntaxOn
\NewDocumentCommand{\replace}{mmm}
 {
  \marian_replace:nnn {#1} {#2} {#3}
 }

\tl_new:N \l_marian_input_text_tl
\tl_new:N \l_marian_search_tl
\tl_new:N \l_marian_replace_tl

\cs_new_protected:Npn \marian_replace:nnn #1 #2 #3
 {
  \tl_set:Nn \l_marian_input_text_tl { #1 }
  \tl_set:Nn \l_marian_search_tl { #2 }
  \tl_set:Nn \l_marian_replace_tl { #3 }
  \regex_replace_all:nnN { \b\u{l_marian_search_tl}\b } { \u{l_marian_replace_tl} } \l_marian_input_text_tl
  \tl_use:N \l_marian_input_text_tl
 }
\ExplSyntaxOff

\begin{document}

\replace{Text should be replaced here, here and here}{here}{\LaTeX{}}

\replace{Text should be replaced here, here and not there}{here}{\LaTeX{}}

\end{document}

enter image description here

A simpler solution that replaces all occurrences:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\replace}{mmm}
 {
  \marian_replace:nnn {#1} {#2} {#3}
 }

\tl_new:N \l_marian_input_text_tl

\cs_new_protected:Npn \marian_replace:nnn #1 #2 #3
 {
  \tl_set:Nn \l_marian_input_text_tl { #1 }
  \tl_replace_all:Nnn \l_marian_input_text_tl { #2 } { #3 }
  \tl_use:N \l_marian_input_text_tl
 }
\ExplSyntaxOff

\begin{document}

\replace{Text should be replaced here, here and here}{here}{\LaTeX{}}

\replace{Text should be replaced here, here and not there}{here}{\LaTeX{}}

\end{document}

enter image description here

2
  • Thank you. Do you know a way to replace this: \replace{\replace{start}{start}{fail}}{fail}{success}\\ \replace{fail,}{fail,}{success} – Marian Nov 25 '14 at 17:14
  • @Marian - I've provided an answer that sets up the macro \replace so that the result of \replace{\replace{start}{start}{fail}}{fail}{success} is correct, viz., "success". – Mico Nov 25 '14 at 20:48
22

enter image description here

\def\replace#1#2#3{%
 \def\tmp##1#2{##1#3\tmp}%
   \tmp#1\stopreplace#2\stopreplace}
\def\stopreplace#1\stopreplace{}

\replace{Text should be replaced here, here and here}{here}{Latex}

\bye

written as plain tex but would work in latex too.

1
  • This is very elegant and the best answer here, congratulations. Unfortunately it is impossible to use such replacing on the token strings when we needn't to expand the tokens. – wipet Dec 3 '14 at 19:14
18

This uses the higher-level macro StrSubstitute from xstring package. Use [0] as first optional parameter to replace all occurences of here, but as egreg stated in a comment, it will also replace in words like where or there

\documentclass{article}

\usepackage{xstring}




\begin{document}

\StrSubstitute[0]{Text should be replaced here, here and here}{here}{Latex}
\end{document}

enter image description here

14

Here's a LuaLaTeX-based solution. It uses Lua's powerful string.gsub function in the definition of the \replace macro. The macro \replace can be used recursively.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode} % for luacode environment and \luastring macro

%% Lua-side code
\begin{luacode}
function myreplace(s,a,b)
  x = string.gsub(s,a,b)
  tex.sprint ( x )
end
\end{luacode}

%% TeX-side code
\newcommand\replace[3]{\directlua{%
  myreplace( \luastring{#1}, \luastring{#2}, \luastring{#3} ) }}

\begin{document}
\replace{Text should be replaced here, here and here.}{here}{Latex}

\replace{\replace{start}{start}{fail}}{fail}{success}

\replace{fail,}{fail,}{success}
\end{document}

Addendum to address the follow-up query by @user61681: If you must replace every single instance of "here" with "LaTeX" in the entire document, and if you can't do so by performing a global search-and-replace operation in your text editor, the following approach may be of interest. It "works" by (a) setting up a Lua function that employs the string.gsub function to replace all instances of "here" with "LaTeX" and (b) assigning this Lua function to LuaTeX's process_input_buffer callback, in effect making it act like a preprocessor on the input stream before TeX starts doing any of its usual work.

Note that this approach will fail is your document contains macros or labels that contain the string here.

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode} 
\begin{luacode}
function myreplace ( s )
   s = s:gsub ( "here" , "LaTeX" ) 
   return s 
end
\end{luacode}
\AtBeginDocument{\directlua{luatexbase.add_to_callback(
   "process_input_buffer", myreplace , "myreplace" )}}

\begin{document}
Text should be replaced here, here and here.
\end{document}
3
  • 1
    How to edit this if I want it for whole tex document. The problem is to replace here by LaTeX everywhere. Of course I can include whole text in curly braces after \replace but something simple may be possible. The question is how to extend this to whole tex document. – user61681 Jul 17 '19 at 15:25
  • @user61681 - Please see the addendum I just posted. – Mico Jul 17 '19 at 16:21
  • Thanks. It works. – user61681 Jul 17 '19 at 18:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.