13

How can I write % into an auxiliary file? % will not work, because LaTeX thinks that I start a comment with it (in the main file, not in the auxiliary file!), and \% will write \% into the file. How can it be accomplished?

\documentclass{article}
\begin{document}
\newwrite\outfile
\immediate\openout\outfile=example.dat
\immediate\write\outfile{%}% will not work, of course, but neither \%
\immediate\closeout\outfile
\end{document}
2

4 Answers 4

13

There is \@percentchar that expands to a literal % character. You need to enclose your writing operation in a \makeatletter \makeatother pair

\makeatletter
\newwrite\outfile
\immediate\openout\outfile=example.dat
\immediate\write\outfile{\@percentchar}
\immediate\closeout\outfile
\makeatother

An alternative with escaping the % inspired by an example where

git log -1 --pretty=format:"%h-%ad" --date=short > /tmp/temp.dat

needs to be passed to \write18

\makeatletter
\newcommand\dosystem{%
  \@ifstar{\@tempswafalse\do@system}{\@tempswatrue\do@system}%
}
\newcommand\do@system[1]{%
  \begingroup
  \let\%\@percentchar
  \if@tempswa\expandafter\immediate\fi
  \write18{#1}%
  \endgroup
}
\makeatother

so the command above can be executed by saying

\dosystem{git log -1 --pretty=format:"\%h-\%ad" --date=short > /tmp/temp.dat }

With \dosystem* the \write is delayed at the next shipout (because \immediate is not executed).

Other characters can be escaped using the same idea, adding other \let instructions. If also braces and # are needed, an extended definition would be

\makeatletter
\newcommand\dosystem{%
  \@ifstar{\@tempswafalse\do@system}{\@tempswatrue\do@system}%
}
\edef\@hashmark{\string#}\edef\@lbrace{\string{}\edef\@rbrace{\string}}
\newcommand\do@system[1]{%
  \begingroup
  \let\%\@percentchar
  \let\#\@hashmark
  \let\{\@lbrace
  \let\}\@rbrace
  \if@tempswa\expandafter\immediate\fi
  \write18{#1}%
  \endgroup
}
\makeatother

and in the argument also \#, \{ and \} can be used for escaping those characters.

1
  • It is worth noting that expl3 provides the constant string \c_percent_str. Commented Aug 18, 2022 at 8:30
5

use \@percentchar or \charxxx where xxx is the decimal number of %

3
  • 1
    \symbol{37} won't write %, but rather \char37.
    – egreg
    Commented Nov 10, 2011 at 19:03
  • 1
    Also \char is unexpandable
    – egreg
    Commented Nov 10, 2011 at 20:43
  • 1
    And being unexpandable I can't use it.
    – Stephen
    Commented Nov 14, 2011 at 18:04
5

As other answers note, you need one way or another to output the string %. For users not using LaTeX, something like

\def\percentchar#1{}
\edef\percentchar{\expandafter\percentchar\string\%}

will generate a macro \percentchar which can be used for this purpose. (I've used \percentchar twice rather than define a 'gobble' command: just to avoid 'name waste'. Many people will have something of that sort set up anyway.) Thus for example with the above

\immediate\write-1{\percentchar}

will write % to the log file.

Another alternative is to alter the category code of %

\begingroup
  \catcode`\%=12
  \immediate\write-1{%}\relax
\endgroup

although this does require a bit more care terminating lines correctly (for example, the \relax above is needed if we cannot assume vertical mode).

4

Following the comment of Martin Scharrer I read up on his newverbs package. With this the following is possible:

\documentclass{article}
\usepackage{newverbs}
\Verbdef\verbpercent{%}
\begin{document}
\newwrite\outfile
\immediate\openout\outfile=example.dat
\immediate\write\outfile{\verbpercent}
\immediate\closeout\outfile
\end{document}

Comparison with the use of \@percentchar:

  • Advantage: \Verbdef can generally be used for any verbatim text, and doesn't require \makeatletter \makeatother.

  • Disadvantage: It uses more of TeX's memory and more time to compile (both: slightly), and theoretically there could be an incompatibility between package newverbs and some other package.

(Therefore I use \@percentchar, but reference to the newverbs package surely is useful for the general case.)

As user202729 pointed out in a comment at May 20th, 2023, in sufficiently new LaTeX versions this solution breaks: How do I write the hashtag symbol # into an output file?. Since 2018/12/01 LaTeX provides the command \protected@file@percent. If example.dat is not further processed with LaTeX but needs an actual "%", then this would not help.

1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .