Das Szenario: Ein Datum in einem yyyy-mm-dd
Formular aus einer Datei in eine CS lesen. Diese CS wird später mit einem Makro „aktuelles Datum“ verglichen, um einige Argumente auf eine bestimmte Weise in eine externe Datei zu schreiben. Das Makro „aktuelles Datum“ ähnelt dem von
% \def\TODAY{}
% \def\Today{\the\year-\TwoDigits{\the\month}-\TwoDigits{\the\day} }
\def\TODAY{\xdef\Today{\the\year-\TwoDigits{\the\month}-\TwoDigits{\the\day}}}
Das funktioniert für die Beschriftung, da \ref{yyyy-mm-dd}
es wie vorgesehen funktioniert. Wenn man kein Extra hat \TODAY
und dann \def
'd Today verwendet, funktioniert es auch, der Vergleich funktioniert nicht. etoolbox
's \ifstrequal
ist nicht das, was ich vorher verwendet habe. Immer wenn sich das Datum änderte, habe ich ein einzelnes verwendet \xdef
und dieses Makro später an ein übergeben \ifx
, und damit es funktioniert, musste ich das Datum mit einem angehängten definieren.bearbeiten„Read to my amazement“ fügt nach dem Gelesenen ein einzelnes Leerzeichen ein.
Momentan bin ich angeblich dabei, Dinge zu reparieren, aber ich habe es irgendwie kaputt gemacht, und jetzt passt es überhaupt nicht mehr. Der erste Übeltäter war, dass mein \TwoDigits
cmd robust war. Ich habe es zurück in geändert, \def
anstatt \NewDocumentCommand
es zu beheben. Letzteres ist für Befehle auf Benutzerebene, also lasse ich das durchgehen. Aber die Ergebnisse des MWE sind mir nicht klar.
0.txt
enthält eine Zeile mit 2001-01-01
und dahinter eine Zeile new, als ob eine Zeile hineingeschrieben und die Ausgabe geschlossen worden wäre.
Die Fragen:
- Was ist die „richtige“ Art, Dinge (Makro, CS, Befehl?) zu vergleichen, die (sollten) in Zeichenfolgen erweitert werden?
- Warum funktioniert es hier nicht
\edef
?\xdef
Ich dachte, es wäre eine vollständige Erweiterung, und tatsächlich hat es vorher funktioniert (meine Versionskontrolle ist so gut wie nicht vorhanden, also ist mir das völlig egal). - Welche Bedeutung hat Robustheit? Gibt es eine einfache Faustregel, wann sie notwendig, obligatorisch oder irrelevant ist?
- Es funktioniert mit
xstring
's\IfStrEqual
nurwennin die Definition von eingefügt wird
\datemacro
und nicht in die Klammern des Vergleichs, also{\datemacro }
. Warum? \ifstrequal
wird angeblich nicht erweitert – ich habe es einmal in einem Befehl verwendet, um zu testen, ob ein Argument gleich ist&
, das funktioniert – zählt es nicht als Erweiterung, wenn Nr. 1 zu der Eingabe wird?
bearbeiten: Ich habe vergessen, \ifx
dass es für Makros verwendet wurde, nicht für abgegrenzte Argumente, tut mir leid.
Beispiel 1;
\documentclass{article}
\usepackage[top=1.5cm, bottom=0.6cm, hmargin=1.5cm]{geometry}
\usepackage{etoolbox}
\newread\periods
\openin\periods=0.txt
\begin{document}\setlength\parindent{0pt}\fontsize{20}{20}\selectfont
\def\testi{2001-01-01}
\edef\testii{2001-01-01}
\def\testiii{2001-01-01 }
\edef\testiiii{2001-01-01 }
\global\read\periods to \DDD
\ifstrequal{\testi}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testiii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testiiii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\DDD}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testi}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testiii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testiiii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\DDD}{\DDD}{T\\}{F\\}% T
\ifx{\testi}{2001-01-01} T\\\else F\\\fi% F
\ifx{\testii}{2001-01-01} T\\\else F\\\fi% F
\ifx{\testiii}{2001-01-01} T\\\else F\\\fi% F
\ifx{\testiiii}{2001-01-01} T\\\else F\\\fi% F
\ifx{\DDD}{2001-01-01} T\\\else F\\\fi% F
\ifx{\testi}{\DDD} T\\\else F\\\fi% F
\ifx{\testii}{\DDD} T\\\else F\\\fi% F
\ifx{\testiii}{\DDD} T\\\else F\\\fi% F
\ifx{\testiiii}{\DDD} T\\\else F\\\fi% F
\ifx{\DDD}{\DDD} T\\\else F\\\fi% F
\ifcsequal{\testi}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testiii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testiiii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\DDD}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testi}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testii}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testiii}{\DDD}{T\\}{F\\}% T
\ifdefequal{\testiiii}{\DDD}{T\\}{F\\}% T
\ifdefequal{\DDD}{\DDD}{T\\}{F\\}% T
\end{document}
Beispiel 2;
\documentclass{article}
\usepackage[top=1.5cm, bottom=0.6cm, hmargin=1.5cm]{geometry}
\usepackage{etoolbox,xstring}
\def\TwoDigits#1{\ifnum#1<10 0#1\else#1\fi}
\newcount\month
\month 1\relax
\newcount\day
\day 1\relax
\newread\periods
\openin\periods=0.txt
\global\read\periods to \DDD
\def\testi{2001-\TwoDigits{\the\month}-\TwoDigits{\the\day}}%
\edef\testii{2001-\TwoDigits{\the\month}-\TwoDigits{\the\day}}%
\def\testiii{2001-\TwoDigits{\the\month}-\TwoDigits{\the\day} }%
\edef\testiiii{2001-\TwoDigits{\the\month}-\TwoDigits{\the\day} }%
\begin{document}\setlength\parindent{0pt}
DDD is \DDD.% space between cs and .
\ifstrequal{\testi}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testiii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testiiii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\DDD}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testi}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testiii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testiiii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\DDD}{\DDD}{T\\}{F\\}% T
\ifx\testi{2001-01-01} T\\\else F\\\fi% F
\ifx\testii{2001-01-01} T\\\else F\\\fi% F
\ifx\testiii{2001-01-01} T\\\else F\\\fi% F
\ifx\testiiii{2001-01-01} T\\\else F\\\fi% F
\ifx\DDD{2001-01-01} T\\\else F\\\fi% F
\ifx\testi\DDD T\\\else F\\\fi% F
\ifx\testii\DDD T\\\else F\\\fi% F
\ifx\testiii\DDD T\\\else F\\\fi% F
\ifx\testiiii\DDD T\\\else F\\\fi% T
\ifx\DDD\DDD T\\\else F\\\fi% T
\ifcsequal{\testi}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testiii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testiiii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\DDD}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testi}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testii}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testiii}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testiiii}{\DDD}{T\\}{F\\}% T
\ifdefequal{\DDD}{\DDD}{T\\}{F\\}% T
\IfStrEq{\testi}{\DDD}{T\\}{F\\}% F
\IfStrEq{\testii}{\DDD}{T\\}{F\\}% F
\IfStrEq{\testi }{\DDD}{T\\}{F\\}% F
\IfStrEq{\testii }{\DDD}{T\\}{F\\}% F
\IfStrEq{\testiii}{\DDD}{T\\}{F\\}% T
\IfStrEq{\testiiii}{\DDD}{T\\}{F\\}% T
\IfStrEq{\DDD}{\DDD}{T\\}{F\\}% T
\end{document}
Antwort1
\ifstrequal
Aus der Dokumentation von etoolbox
:
\ifstrequal{⟨string⟩}{⟨string⟩}{⟨true⟩}{⟨false⟩}
Vergleicht zwei Zeichenfolgen und führt ⟨true⟩ aus, wenn sie gleich sind, und andernfalls ⟨false⟩. Die Zeichenfolgen werden im Test nicht erweitert und der Vergleich ist kategoriecodeunabhängig. Kontrollsequenztoken in einem der ⟨Zeichenfolgen⟩-Argumente werden detokenisiert und als Zeichenfolgen behandelt. Dieser Befehl ist robust.
Daher \ifstrequal{\testi}{...}
wird true nicht zurückgegeben, es sei denn, ...
es ist genau dasselbe wie\testi
als Zeichenfolgen.
Andererseits,
\expandafter\ifstrequal\expandafter{\DDD}{2001-01-01 }{T}{F}
gibt zurück , aber beachten Sie den nachfolgenden Zwischenraum, der durch das Erkennen eines Zeilenendes T
entsteht .\read
\ifx
Dies ist ein primitiver Bedingungssatz und sollte mit der richtigen Syntax verwendet werden: \ifx AB
vergleicht die Token A
und B
ohne Erweiterung. Daher wird mit \ifx{\DDD}...
verglichen .{
\DDD
\ifcsequal
\ifcsequal{⟨csname⟩}{⟨csname⟩}{⟨true⟩}{⟨false⟩}
Ähnlich wie\ifdefequal
, außer dass es Steuersequenznamen als Argumente verwendet.
Somit werden sowohl als auch \ifcsequal{\testi}{\DDD}
erweitert , es ist also dasselbe wie das Ausführen von , das „false“ zurückgibt, weil die beiden erstellten Steuersequenzen beide gleichwertig sind mit .\testi
\DDD
\ifcsequal{2001-01-01}{2001-01-01 }
\relax
\ifdefequal
Hier erhalten Sie schließlich den Code, der true zurückgibt. Beachten Sie, dass, wenn Sie
\def\testiii{2001-\TwoDigits{\the\month}-\TwoDigits{\the\day} }%
dann \ifdefequal{\testiii}{\DDD}
wird zurückkehrenFALSCH, weil es sich nur um die Erweiterung der ersten Ebene handelt. Andererseits \edef
ist die Version das, was funktioniert.
\IfStrEq
Dadurch werden die Argumente vollständig erweitert (unter normalen Bedingungen), sodass der Vergleich mit „oder“ \testiiii
funktioniert \testiiii
.
Robustheit
Die Robustheit von \ifstrequal
ist völlig irrelevant. Naja, eigentlich nicht ganz. Wenn Ihre TeX-Engine dies unterstützt \expanded
(alle werden es in ein paar Wochen mit der Veröffentlichung von TeX Live 2019 tun), dann etwas wie
\expanded{\ifstrequal}{\testiii}{\DDD}{T}{F}}
wird zurückkehren T
und die Robustheit \ifstrequal
ist entscheidend dafür, dass dies funktioniert.
Nutzen Sie den Arbeitstest.