5

I have a LaTeX document with several authors that I enter like \author{First Author \& Second Author \& .... In some places in the document I want to print these authors with a linebreak behind every name, i.e. I want to replace all occurences of \& by \\ (or an equivalent command).

I found this question about an almost identical issue, except that no linebreak is to be inserted. Trying \StrSubstitute{text \& text}{ \& }{\\} I get a whole bunch of errors and no output. The linebreak seems to break the \StrSubstitute macro.

Is there a way to prevent this from failing? If not, what other approach will work?

  • Typically \author stores its argument in \@author, which is cleared after a call to \maketitle. What do you use in order to access this via \theauthor? Please answer this in the form of a minimal working example (MWE). – Werner May 16 '14 at 20:57
  • Check \noexpandargs in the documentation of xstring – egreg May 16 '14 at 20:59
  • @Werner: Right, I forgot about that. I use the titling package which provides \theauthor. I replaced it by plain text in my question. David's suggestion works like a charm, so I don't think, a MWE is necessary anymore. – schtandard May 16 '14 at 21:51
6

TeX is a macro expansion language: do not use string substitution: simply redefine the macro

{\renewcommand\&{\\} \theauthor}

will evaluate \theauthor in a local context where \& means linebreak.

7

David's answer is precious, efficient and nice for the problem at hand. However, it doesn't deal with the error you get.

The package xstring has three modes of operations:

  1. \fullexpandarg
  2. \expandarg
  3. \noexpandarg

and the first is the default. They are described in section 3.1.1 of the manual, together with the list of what arguments of the provided commands are subject to this expansion. In the case of \StrSubstitute, all arguments but the trailing optional one are influenced by the mode of operation. So your

\StrSubstitute{\theauthor}{\&}{\\}

will do full expansion of \theauthor, \& and \\. You may be were lucky enough that \theauthor survives full expansion (it does if authors' names don't contain accented letters); \& is not dangerous, because it's internally defined with \chardef, which makes it unexpandable; \\ will definitely not survive full expansion, because its operations require doing definitions.

Now you know that \fullexpandarg is not good, but \noexpandarg isn't either, because you want to expand \theauthor once or \& wouldn't be found: you need the list of authors' names, not the macro containing them. What can you do? There are several possibilities.

Use \expandarg

\saveexpandmode % remember what's the current mode of operations
\expandarg % operation mode where only one step of expansion is performed
\StrSubstitute{\theauthor}{\&}{\noexpand\\}
\restoreexpandmode % restore the previous mode of operations

Use \noexpandarg

\saveexpandmode % remember what's the current mode of operations
\noexpandarg % operation mode where only one step of expansion is performed
\expandafter\StrSubstitute\expandafter{\theauthor}{\&}{\\}%
\restoreexpandmode % restore the previous mode of operations

Choose the method you like better. You can also say \expandarg or \noexpandarg in the preamble after \usepackage{xstring}, changing mode when you need a different one.

Changing the mode will also respect grouping, so

\begingroup
\expandarg % operation mode where only one step of expansion is performed
\StrSubstitute{\theauthor}{\&}{\noexpand\\}%
\endgroup

would restore the previous mode. If you just need printing the changed token list, then this may be sufficient. Of course \renewcommand{\&}{\\} is more efficient, but in other cases you might need these tricks.


A different strategy is with l3regex:

\usepackage{xparse,l3regex}

\ExplSyntaxOn
\NewDocumentCommand\printauthors{O{\\}}
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_set_eq:NN \l_tmpb_tl \theauthor
  \regex_replace_all:nnN { \c{&} } { \u{l_tmpa_tl} } \l_tmpb_tl
  \tl_use:N \l_tmpb_tl
 }
\ExplSyntaxOff

Then \printauthors would do the same substitution as you want; with \printauthors[<something else>] you can change \& into whatever you like.

  • Wow, great answer! However, there seems to be a missing backtick in your last paragraph even swallowing some text. – schtandard May 17 '14 at 11:19
  • 1
    @schtreber Thanks for noticing; it should be fixed, now. – egreg May 17 '14 at 16:58
  • Update: l3regex should not be loaded with recent versions of expl3. – egreg Jan 16 at 15:42

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.