如何正確地將讀取的字串與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不是\ifstrequal我以前用過的。每當日期發生變化時,我都會使用單一\xdef巨集,然後將該巨集傳遞給 a \ifx,為了使其正常工作,我必須在附加的情況下定義日期編輯令我驚訝的是,閱讀後會在閱讀的內容後插入一個空格。

目前我應該正在修復一些東西,但我以某種方式破壞了它,現在它根本不匹配。第一個罪魁禍首是我的\TwoDigits命令很強大,將其改回\def而不是\NewDocumentCommand修復它。後者用於用戶級命令,所以我就不說了。但我不清楚 mwe 的結果。

0.txt包含一行 with2001-01-01和一行 new,就好像已寫入一行並且輸出已關閉。

問題:

  1. 比較事物(宏、cs、命令?)的「正確」方法是什麼(應該)擴展到字串?
  2. 為什麼不在這裡\edef工作\xdef,我認為這是一個完整的擴展,而且實際上之前(我的版本控制幾乎不存在,所以我對此無法給予關注)它起作用了。
  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比較標記A且不B進行擴展。因此\ifx{\DDD}...{與進行比較\DDD

\ifcsequal

\ifcsequal{⟨csname⟩}{⟨csname⟩}{⟨true⟩}{⟨false⟩}
與此類似\ifdefequal,只是它採用控制序列名稱作為參數。

因此\ifcsequal{\testi}{\DDD}將展開\testi\DDD,因此它與執行 which 返回 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

這會完全擴展其參數(在正常情況下),因此與\testiiiior 的比較\testiiii有效。

穩健性

的穩健性\ifstrequal完全無關。嗯,實際上並不完全。如果您的 TeX 引擎支援\expanded(隨著 TeX Live 2019 的發布,所有這些都將在幾週內實現),例如

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

將會回歸T,而其穩健性\ifstrequal對於其發揮作用至關重要。

使用工作測試。

相關內容