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.
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}
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
Try the xstring
package:
\usepackage{xstring}
[…]
\StrSubstitute{File,New}{,}{\(\rightarrow\)}
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}\\
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With