10

I've tried to use \protect to make the following \edef work but no luck. Can it be done somehow?

\documentclass{article}

\usepackage{xstring}

\begin{document}

\def\abc{a,b,c}
\edef\result{\StrSubstitute[2]{\abc}{,}{ }}

\result

\end{document}

NOTE: I know I can do the same using etoolbox or xpatch (and I already did that), but became curious about the problem above.

  • 1
    Short answer: you can't. – egreg Nov 23 '13 at 21:40
  • I had answered prior to your reply here. ;-) – egreg Nov 23 '13 at 22:01
14

The answer is pretty simple: you can't.

The instruction \edef works purely by expansion; no assignment can be performed during an \edef: when TeX finds an unexpandable token in \edef it passes over it and proceeds with the next token.

So you can't say

\newcount\baz
\edef\foo{\advance\baz 1 \number\baz}

and hope that \foo expands to 1. It will expand to

\advance\baz 1 0

because \advance, \baz and 1 are unexpandable, while \number is expandable. Just try it in an interactive session:

This is TeX, Version 3.1415926 (TeX Live 2013)
**\relax

*\newcount\baz

*\edef\foo{\advance\baz 1 \number\baz}

*\show\foo
> \foo=macro:
->\advance \baz 1 0.
<*> \show\foo

With \StrSubstitute several assignments are made; not only operations on registers are assignments, but also \def\ and \let are.

The correct way to define \result to contain the result of the substitution is

\StrSubstitute[2]{\abc}{,}{ }[\result]

The trailing optional argument can be used in most xstring macros.

Here's the test file:

\documentclass{article}

\usepackage{xstring}

\begin{document}

\def\abc{a,b,c}
\StrSubstitute[2]{\abc}{,}{ }[\result]

\texttt{\meaning\result}

\end{document}

enter image description here

  • I've learnt many things from this answer, thank you. – masu Nov 23 '13 at 23:20

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.