Eingabe-/Ausgabeprimitive von TeX

Eingabe-/Ausgabeprimitive von TeX

Ich möchte einige einfache Makros für die Handhabung von Dingen wie Querverweisen schreiben, um sie in reinem TeX zu verwenden. (Ich weiß, dass es bereits Makros dafür gibt, wie die in Eplain, aber ich möchte selbst etwas anderes ausprobieren.) Ich muss also wissen, wie man aus einer Datei liest und wie man in eine Datei schreibt. Welche TeX-Grundelemente tun solche Dinge? Wie funktionieren sie?

Eine weitere Frage: Kann TeX während der Ausführung andere Programme „aufrufen“? Ich meine: Gibt es in TeX ein Äquivalent zur Systemfunktion, die in der Sprache C vorhanden ist?

Antwort1

TeX verfügt über die \readund \writePrimitive zum Lesen und Schreiben in Dateien und natürlich auch \inputzum Eingeben einer ganzen Datei „hier“. Wenn Sie sich beispielsweise den Querverweismechanismus von LaTeX ansehen, wird dieser verwendet, \writevermeidet jedoch die Verwendung \read(zeilenweise) zugunsten der Verwendung von \inputmit entsprechend gestalteten sekundären Dateien.

Da \inputdies leicht zu verstehen ist, konzentrieren wir uns auf \readund \write. Beide arbeiten mit einem Dateistream, der eine Nummer erhält, aber normalerweise mit zugewiesen wird \new.... Zum Beispiel

\newread\myread
\openin\myread=myinput %

\newwrite\mywrite
\immediate\openout\mywrite=myoutput %

richtet einen Lesevorgang namens \myreadund einen Schreibvorgang namens ein. Beachten Sie, dass ich mit \mywriteverwendet habe : Aufgrund der asynchronen Natur des TeX-Seitenerstellers müssen Sie sicherstellen, dass die Vorgänge an der „richtigen“ Stelle stattfinden. (Weitere Informationen hierzu finden Sie weiter unten.)\immediate\write\write

Mit zwei geöffneten Streams können wir beispielsweise in die Ausgabe schreiben. Wenn wir zwei Schreibvorgänge durchführen, einen „jetzt“ und einen „verzögert“

\def\foo{a}
\immediate\write\mywrite{\foo}
\write\mywrite{\foo}
\def\foo{b}
Hello
\bye

Das Ergebnis myoutput.texlautet

a
b

Das liegt daran, dass \write\mywriteein Dingsbums erzeugt wird, das nur ausgeführt wird, wenn eine Seite ausgeliefert wird. Das ist beispielsweise nützlich, wenn das, was Sie schreiben müssen, eine Seitenzahl enthält, da diese nur während der Ausgabephase bekannt ist. Beachten Sie auch, dass \writesich wie verhält \edef: Alles wird erweitert, sofern Sie es nicht mit \noexpandoder einem verhindern toks. Beachten Sie jedoch, dass diese Erweiterung in dem Moment durchgeführt wird \write, in dem die Operation tatsächlich ausgeführt wird. Daher muss sichergestellt werden, dass Makros bei Verwendung eines verzögerten korrekt definiert sind \write.

Das \readPrimitiv liest jeweils eine Zeile (sofern keine Klammern übereinstimmen) und tokenisiert auf die normale TeX-Art. Sie können eine Datei zeilenweise durchlaufen lassen, indem Sie den \ifeofTest auf verwenden \myread, aber wie ich schon sagte, ist es oft einfacher, einfach \inputeine Datei mit Querverweisen zu verwenden.

Wenn Sie einen Systemaufruf durchführen möchten, hilft Ihnen „reines“ TeX nicht wirklich weiter. Web2c verfügt jedoch schon seit langem über einen speziellen „Stream“, der das Verlassen des Systems ermöglicht: \write18. Dies stellt ein Sicherheitsrisiko dar, und standardmäßig ist bei einem solchen Verlassen nur eine begrenzte Anzahl von Befehlen zulässig. Sie können beispielsweise

pdftex --shell-escape myfile

um alles entkommen zu lassen: das Risiko, wenn Sie den gesamten Code selbst geschrieben haben, besteht nur darin, dass Sie Fehler machen! Wenn Sie ein ausführen, \write18wird nichts an TeX zurückgegeben: Sie müssen dafür sorgen, dass das Ergebnis irgendwie gelesen wird, wahrscheinlich mithilfe \readeiner sekundären Datei.

Wie in einem Kommentar erwähnt, ist eine zusätzliche Syntaxerweiterung verfügbar \input|"<command>". Diese ist zwar wieder eingeschränkt, \write18bietet aber eine erweiterbare Methode, um Eingaben von Shell-Befehlen abzurufen.

Antwort2

Eine weitere Besonderheit beim Umgang mit Querverweisen über externe Dateien ist die Reihenfolge des Lesens, Öffnens, Schreibens und Schließens dieser Datei. Das grundlegende Schema ist:

\newwrite\fileout  % allocations of the file number

\def...     ... all macros which can be used in the file must be defined
\input file ... input only when file exists (the file doesn't exist at the first run)
            ... this input stores the data from file into internal macros
\immediate\openout\fileout=file  ... this removes the data from file
                                  ... the file has zero length now

... document ... macros used in the document write (typically not immediately) 
                 data to the file

\end ... this closes the file automatically, 
         but if you need to use the data from the file at the end of the document
         (for example the TOC at the end of the document):
\vfil\eject  
\immediate\closeout\fileout
\input file ... this creates the TOC at the end of the file.
\end

Das obige Schema zeigt, dass Sie ein Makro erstellen müssen, das die Datei \inputnur liest, wenn diese Datei vorhanden ist. Sie können für solche Zwecke das folgende \softinputMakro verwenden:

\newread\testin
\def\softinput #1 {\let\next=\relax \openin\testin=#1
   \ifeof\testin \message{Warning: the file #1 does not exist}%
   \else \closein\testin \def\next{\input #1 }\fi
   \next}

verwandte Informationen