如何正确地将字符串与读取的 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,我以为这是一个完整的扩展,事实上之前(我的版本控制几乎没有,所以我不能给出一个mwe)它起作用了。
  3. 稳健性的意义何在?当它是必要的、强制性的或不相关的时,是否有一个简单的经验法则?
  4. xstring它与\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比较标记AB而不进行扩展。因此\ifx{\DDD}...{与进行比较\DDD

\ifcsequal

\ifcsequal{⟨csname⟩}{⟨csname⟩}{⟨true⟩}{⟨false⟩}
类似于,\ifdefequal只是它以控制序列名称作为参数。

因此\ifcsequal{\testi}{\DDD}将扩展\testi\DDD,所以它与执行返回 false 的操作相同,\ifcsequal{2001-01-01}{2001-01-01 }因为两个构建的控制序列都等同于\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对于其工作起着决定性的作用。

使用工作测试。

相关内容