Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace a character with a string in LaTeX

Tags:

latex

I'm looking for a way to do a substring replace on a string in LaTeX. What I'd like to do is build a command that I can call like this:

\replace{File,New}

and that would generate something like

\textbf{File}$\rightarrow$\textbf{New}

This is a simple example, but I'd like to be able to put formatting/structure in a single command rather than everywhere in the document. I know that I could build several commands that take increasing numbers of parameters, but I'm hoping that there is an easier way.

Edit for clarification

I'm looking for an equivalent of

string.replace(",", "$\rightarrow$)

something that can take an arbitrary string, and replace a substring with another substring.

So I could call the command with \replace{File}, \replace{File,New}, \replace{File,Options,User}, etc., wrap the words with bold formatting, and replace any commas with the right arrow command. Even if the "wrapping with bold" bit is too difficult (as I think it might be), just the replace part would be helpful.

like image 567
Matt McMinn Avatar asked Sep 18 '08 19:09

Matt McMinn


4 Answers

The general case is rather more tricky (when you're not using commas as separators), but the example you gave can be coded without too much trouble with some knowledge of the LaTeX internals.

\documentclass[12pt]{article}
\makeatletter
\newcommand\formatnice[1]{%
  \let\@formatsep\@formatsepinit
  \@for\@ii:=#1\do{%
    \@formatsep
    \formatentry{\@ii}%
  }%
}
\def\@formatsepinit{\let\@formatsep\formatsep}
\makeatother
\newcommand\formatsep{,}
\newcommand\formatentry[1]{#1}
\begin{document}
\formatnice{abc,def}

\renewcommand\formatsep{\,$\rightarrow$\,}
\renewcommand\formatentry[1]{\textbf{#1}}
\formatnice{abc,def}
\end{document}
like image 187
Will Robertson Avatar answered Oct 19 '22 05:10

Will Robertson


it looks like your "spaces" problem is from a bug in that package. If you surround the "\GetTokens" macro with, say, commas, then you'll see that the extra space is inserted by that macro.

Yes there are bugs in tokenizer package. As I said on my blog, the bugfix is to use the following correcting code instead of just "\usepackage[trim]{tokenizer}":

\usepackage[trim]{tokenizer}  

\def\SH@GetTokens#1,#2\@empty{%
    \def\SH@token{#1}%
    \ifx\SH@trimtokens\SH@true% strip spaces if requested
        \TrimSpaces\SH@token%
    \fi%
    \SH@DefineCommand{\SH@FirstArgName}{\SH@token}%
    \SH@DefineCommand{\SH@SecondArgName}{#2}%
    }
\def\SH@CheckTokenSep#1,#2\@empty{%
    \def\SH@CTSArgTwo{#2}%
    \ifx\SH@CTSArgTwo\@empty%
        \edef\SH@TokenValid{\SH@false}%
    \else%
        \edef\SH@TokenValid{\SH@true}%
    \fi%
    }

I will report this bugfix to the developer Sascha Herpers

like image 29
Becheru Petru-Ioan Avatar answered Oct 19 '22 05:10

Becheru Petru-Ioan


Try the xstring package:

\usepackage{xstring}

[…]

\StrSubstitute{File,New}{,}{\(\rightarrow\)}
like image 33
Paul Biggar Avatar answered Oct 19 '22 05:10

Paul Biggar


There's a LaTeX package called tokenizer which may help you to do what you want.

Here's a hack (but pure LaTeX, no internals) which gets close to what I think you want, but with some extraneous spaces I haven't quite been able to fix. Perhaps Will Robertson can advise further? Unlike his slightly more polished answer, I haven't parameterised the bits and pieces, Here goes:

\usepackage{forloop}  
\usepackage[trim]{tokenizer}  
...  
\newcounter{rrCount}  
\newcommand{\replace}[1]{%  
    \GetTokens{rrFirst}{rrRest}{#1,}%  
    \textbf{\rrFirst}%  
    \forloop{rrCount}{0}{\value{rrCount} < 100}{%  
        \ifthenelse{\equal{\rrRest}{}}{%  
            \setcounter{rrCount}{101}%  
        }{%  
            \GetTokens{rrFirst}{rrRest}{\rrRest}%  
            $\rightarrow$\textbf{\rrFirst}%  
        }%  
    }%  
}%  
% -----------------------------------------------------------------  
\replace{a1}\\  
\replace{a2,b2}\\  
\replace{a3,b3,c3}\\  
like image 28
Brent.Longborough Avatar answered Oct 19 '22 04:10

Brent.Longborough