Situation

Situation

Wenn ich das Rautezeichen/Nummernzeichen/Hash-Zeichen #in Befehlen und Umgebungen verwende, bezieht sich dies auf Argumente. Es sollte jedoch nicht \detokenize{#}dazu führen , dassNICHTein Argument?

Situation

Das Nummernzeichen dient als praktische Trennlinie in Protokolldateien.

Beispiel

Versuchen Sie, das zweite Kommentarfeld zu entfernen, \detokenizeum eine Fehlermeldung zu erhalten.

\documentclass{article}
\usepackage{fontspec}% compile with xelatex
\newenvironment{detokenizetest}[1]
{% firstoftwo
 \detokenize{##############################################################################}%
 %\detokenize{##BEGIN#######################################################################}% uncommenting this causes a compile error
}%
{% secondoftwo
}%
\begin{document}
\null
\end{document}

Fehlerausgabe

Dieser Fehler tritt nur auf, wenn die Zeile, die enthält, auskommentiert wird BEGIN.

! Illegal parameter number in definition of \detokenizetest.
<to be read again>
                   }
l.9 }
     %
?

Antwort1

Da #es den Kategoriecode 6 hat, hat es in TeX eine ganz besondere Bedeutung, weil es zur Bezeichnung von Parametern in Makrodefinitionen verwendet wird.

Die Regeln von TeX besagen, dass Sie, wenn Siespeicherna #im Ersetzungstext eines Makros, müssen Sie es verdoppeln.

Bei der Verarbeitung des Ersetzungstextes für eine Makrodefinition #muss auf eine einzelne Ziffer eine Ziffer (1 bis 9) folgen, die einen Zeiger auf das entsprechende Argument bezeichnet, wobei ##als gespeichert wird #. Mit diesem Trick können Sie so etwas wie

\def\foo{\def\baz##1{-##1-}}

Der Ersetzungstext von \fooist daher \def\baz#1{-#1-}und ein Aufruf von \foowird \bazals Makro mit einem einzigen Argument definiert.

Das Primitiv \detokenizeim Ersetzungstext wird seine Arbeit verrichtenwenn das Makro aufgerufen und erweitert wird, nicht zum Definitionszeitpunkt, es sei denn, die Definition erfolgt mit \edef, wodurch zunächst eine vollständige Erweiterung durchgeführt wird, bevor der Ersetzungstext im Speicher abgelegt wird.

Beachten Sie, dass Ihnen in diesem Fall \meaning\foo(unter der Annahme der obigen Definition) Folgendes angezeigt wird:

macro:->\def \baz ##1{-##1-}

und das gleiche wird passieren, \detokenizewenn der gleiche Mechanismus verwendet wird. Also so etwas wie

\edef\hashmarks{\detokenize{####}}

#wird tatsächlich zwei im Ersetzungstext sehen , aber das Endergebnis wird vier davon sein. Der Standardmechanismus bei der Verarbeitung \edefhalbiert zunächst die Anzahl #und \detokenizeverdoppelt sie dann wieder. Insbesondere SiekippenErzeugen Sie auf diese Weise eine ungerade Anzahl von #.

Wenn Sie Trennlinien erstellen möchten, ist es viel besser, eine indirekte Methode zu verwenden und im Voraus die erforderliche Tokenliste bestehend aus #mit dem Kategoriecode 12 zu erstellen. Im Beispiel verwende ich drei davon, nur weil es eine ungerade Zahl ist.

\documentclass{article}

\begingroup\lccode`?=`# \lowercase{\endgroup
  \newcommand{\lineofhashsigns}{???}
}

\newenvironment{delimitedtext}
  {\par\lineofhashsigns\par}
  {\par\lineofhashsigns\par}

\begin{document}

\begin{delimitedtext}
abc
\end{delimitedtext}

\end{document}

Bildbeschreibung hier eingeben

Eine andere Definition hierfür ist \lineofhashsignsnicht erforderlich, \lowercaseindem der Kategoriecode geändert wird:

\catcode`#=12
\newcommand{\lineofhashsigns}{###}
\catcode`#=6

Sie können im Ersetzungstext beliebige Token hinzufügen, solange das Makro keine Argumente enthalten soll.

Antwort2

Das \detokenizePrimitiv bedeutet in der Tat, dass #nicht als Parameter behandelt wird, sondern als einer, wenn es erweitert wird. Denken Sie daran, dass bei einer normalen Zuweisung ( \newcommandin LaTeX \defals TeX-Primitiv) keine Erweiterung stattfindet. Hier \newenvironmentwird genau dasselbe „einfach speichern“ der Token durchgeführt wie \newcommand. Dies bedeutet, dass wir die übliche TeX-Regel haben, dass wir beim Erstellen eines Makros die passenden Parameter für jedes vorhanden haben müssen #oder die Token verdoppelt werden müssen #.

Da \newenvironmentsich letztendlich ein ergibt \def, können wir mit folgendem tun, was Sie möchten \edef:

\edef\detokenizetest#1{%
 \detokenize{##############################################################################}%
 \detokenize{##BEGIN#######################################################################}%
}
\def\enddetokenizetest{}% As \newenvironment will do this
\show\detokenizetest

verwandte Informationen