Как правильно сравнить строку с cs из чтения?

Как правильно сравнить строку с cs из чтения?

Сценарий: чтение даты в yyyy-mm-ddформе из файла в cs. Этот cs позже сравнивается с макросом «текущая дата», чтобы записать несколько аргументов определенным образом во внешний файл. Макрос текущего дня похож на

% \def\TODAY{}
% \def\Today{\the\year-\TwoDigits{\the\month}-\TwoDigits{\the\day} }
\def\TODAY{\xdef\Today{\the\year-\TwoDigits{\the\month}-\TwoDigits{\the\day}}}

Это работает для маркировки вещей, так как \ref{yyyy-mm-dd}работает так, как и предполагалось. Не имея дополнительных \TODAYи затем используя \def'd Today, это делает то, что не работает, это сравнение. etoolbox's \ifstrequal- это не то, что я использовал раньше. Всякий раз, когда дата менялась, я использовал один \xdefи позже передавал этот макрос в \ifx, и чтобы заставить его работать, мне приходилось определять дату с добавленным.редактироватьПрочитанное к моему изумлению вставляет один пробел после всего прочитанного.

В настоящее время я, как предполагается, что-то чиню, но я как-то сломал его, и теперь он вообще не совпадает. Первым виновником был мой \TwoDigitscmd, который был устойчив, и я изменил его обратно на \defвместо того, чтобы \NewDocumentCommandисправить это. Последнее относится к командам уровня пользователя, так что я промолчу об этом. Но результаты mwe мне не ясны.

0.txtсодержит одну строку 2001-01-01и одну новую строку после нее, как будто в нее была записана одна строка, а вывод был закрыт.

Вопросы:

  1. Каков «правильный» способ сравнения вещей (макросов, CS, команд?), которые (должны) расширяться до строк?
  2. Почему бы и нет \edef, \xdefпоработайте здесь, я думал, что это полноценное расширение, и действительно, раньше (у меня почти нет системы контроля версий, так что я не могу сказать, что это такое) это работало.
  3. В чем значение надежности? Есть ли простое правило, когда это необходимо, обязательно или неактуально?
  4. Он работает с xstring's\IfStrEqual толькоесли вставлено в определение \datemacro, а не в скобки сравнения, т.е. {\datemacro }. Почему?
  5. \ifstrequalпредположительно не расширяется - я использовал один раз в команде, чтобы проверить, равен ли аргумент &, это работает - становится ли #1 тем, что было введено, не считается расширением?

редактировать: Я забыл, \ifxчто используется для макросов, а не для разделенных аргументов, извините.

пример 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}

пример 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}

решение1

\ifstrequal

Из документации etoolbox:

\ifstrequal{⟨string⟩}{⟨string⟩}{⟨true⟩}{⟨false⟩}
Сравнивает две строки и выполняет ⟨true⟩, если они равны, и ⟨false⟩ в противном случае. Строки не расширяются в тесте, и сравнение не зависит от кода категории. Токены управляющей последовательности в любом из аргументов ⟨string⟩ будут детокенизированы и обработаны как строки. Эта команда надежна.

Поэтому \ifstrequal{\testi}{...}не вернет true, если только не ...будет точно таким же, как\testi как струны.

С другой стороны,

\expandafter\ifstrequal\expandafter{\DDD}{2001-01-01 }{T}{F}

вернет T, но обратите внимание на завершающий пробел, который образуется при \readпоявлении конца строки.

\ifx

Это примитивное условное выражение, и его следует использовать с его правильным синтаксисом: \ifx ABсравнивает токены Aи Bбез расширения. Поэтому \ifx{\DDD}...будет сравнивать {с \DDD.

\ifcsequal

\ifcsequal{⟨csname⟩}{⟨csname⟩}{⟨true⟩}{⟨false⟩}
Аналогично , за \ifdefequalисключением того, что в качестве аргументов он принимает имена управляющих последовательностей.

Таким образом \ifcsequal{\testi}{\DDD}будут расширены \testiи \DDD, так что это то же самое, что и выполнение \ifcsequal{2001-01-01}{2001-01-01 }, которое возвращает false, поскольку обе построенные управляющие последовательности эквивалентны \relax.

\ifdefequal

Здесь вы наконец-то получаете код, который возвращает true. Обратите внимание, что если вы используете

\def\testiii{2001-\TwoDigits{\the\month}-\TwoDigits{\the\day} }%

затем \ifdefequal{\testiii}{\DDD}вернетсяЛОЖЬ, потому что он просто смотрит на расширение первого уровня. С другой стороны, версия \edef— это то, что работает.

\IfStrEq

Это делает полное расширение его аргументов (при нормальных условиях), поэтому сравнение с или \testiiiiработает \testiiii.

Надежность

Надежность \ifstrequalсовершенно не важна. Ну, не совсем, на самом деле. Если ваш движок TeX поддерживает \expanded(все будут через несколько недель, с выходом TeX Live 2019), что-то вроде

\expanded{\ifstrequal}{\testiii}{\DDD}{T}{F}}

вернется T, и надежность \ifstrequalимеет решающее значение для его работы.

Используйте рабочий тест.

Связанный контент