
Ich habe den folgenden einfachen Tex-Code:
\def\xx{ABC}
\def\temp #1 {\def\tempii{#1}}
\temp\xx a b c
\tempii\tempii
Ich erwarte die folgende Ausgabe:
a b c ABCABC
Aber ich sehe tatsächlich Folgendes:
b c ABCaABCa
Warum wird das „a“ in die Definition von \tempii hineingeklaut?
Antwort1
Ich denke immer noch darüber nach, warum das so ist, aber diese Überarbeitung (die Folgendes umfasst \xx
) gibt Ihnen, was Sie wollen.
Ich denke, die Antwort ist, dass \temp\xx a b c
das Leerzeichen nach \xx
aus der Sicht des TeX-Parsers überhaupt kein Leerzeichen ist, sondern lediglich das Ende des Makronamens anzeigt \xx
. Wenn Sie beispielsweise einfach \xx A
eine Zeile allein einfügen, werden Sie sehen, dass sie als ABCA
ohne Leerzeichen ausgegeben wird. Der Parser saugt also das nachfolgende „A“ als mit verbunden auf \xx
. Man könnte auch , verwenden \temp\xx{} a b c
, um dem Parser mitzuteilen, dass das Leerzeichen ein Trennzeichen ist und nicht nur das nächste Zeichen nach \xx
.
\documentclass{article}
\begin{document}
\def\xx{ABC}
\def\temp #1 {\def\tempii{#1}}
\temp{\xx} a b c
\tempii\tempii
\end{document}
Antwort2
Der Übersichtlichkeit halber werde ich Leerzeichen-Token mit kennzeichnen •
, da sie in der Diskussion sehr wichtig sind. Leerzeichen in den folgenden Codebeispielen sollten ignoriert werden.
Der Parametertext von \temp
ist
#1•
während der Ersatztext
\def\tempii{#1}
Ihr Anruf \temp
ist
\temp\xx a•b•c•\tempii\tempii
Beachten Sie, dass danach \xx
ein Leerzeichen nur zur Abgrenzung des Makros folgt; es istnichtein Leerzeichen: es ist nichts, weil TeX Leerzeichen nach Kontrollzeichen immer ignoriert.Wörter(nicht kontrollierenSymbole). Das Leerzeichen danach c
stammt vom Zeilenende in Ihrem Code.
Die folgenden Token \temp
werden (ohne Erweiterung) durchsucht, um eine Übereinstimmung mit dem Parametertext zu finden, wobei das Argument durch ein Leerzeichen getrennt ist, sodass #1
es endet \xx a
und der nächste Zustand des Eingabestroms ist
\def\tempii{\xx a}b•c•\tempii\tempii
Nun führt TeX die Definition aus und entfernt sie aus dem Eingabestrom:
b•c•\tempii\tempii
und der Teil b•c•
wird an die Satzphase übergeben. Nach der Erweiterung der beiden Kopien von \tempii
ist dies gleichbedeutend mit dem Eintippen von
b•c•\xx a\xx a
oder
b•c•ABCaABCa
und das ist genau das, was Sie bekommen haben.
\?
Wenn Sie stattdessen verwendet hätten, \xx
wären die letzten beiden Zeilen umgewandelt worden in
\temp\?•a•b•c•\tempii\tempii
weil \?
es sich um ein Steuersymbol handelt und TeX Leerzeichen danach nicht ignoriert. In diesem Fall wäre das Ergebnis
a•b•c•ABCABC
Beachten Sie, dass
\expandafter\temp\xx a•b•c
\tempii\tempii
würde das gleiche Ergebnis liefern, denn nach der Aktion von \expandafter
TeX würde präsentiert werden mit
\temp ABCa•b•c
(natürlich dieselbe Konvention für Leerzeichen wie zuvor). Sie erhalten dasselbe Ergebnis wie mit \?
statt \xx
mit
\expandafter\temp\expandafter\xx\space a•b•c
denn dann würde TeX präsentiert werden mit
\temp\xx•a•b•c
Tatsächlich werden Leerzeichen nach Steuerwörtern nur während des Tokenisierungsprozesses ignoriert.