場景:從檔案讀取表單中的日期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,就好像已寫入一行並且輸出已關閉。
問題:
- 比較事物(宏、cs、命令?)的「正確」方法是什麼(應該)擴展到字串?
- 為什麼不在這裡
\edef
工作\xdef
,我認為這是一個完整的擴展,而且實際上之前(我的版本控制幾乎不存在,所以我對此無法給予關注)它起作用了。 - 穩健性有何意義?當它是必要的、強制性的或無關緊要的時候,是否有一個簡單的經驗法則?
xstring
它與一起工作\IfStrEqual
僅有的如果插入到 的定義中
\datemacro
,而不是比較的括號中,即{\datemacro }
。為什麼?\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
這會完全擴展其參數(在正常情況下),因此與\testiiii
or 的比較\testiiii
有效。
穩健性
的穩健性\ifstrequal
完全無關。嗯,實際上並不完全。如果您的 TeX 引擎支援\expanded
(隨著 TeX Live 2019 的發布,所有這些都將在幾週內實現),例如
\expanded{\ifstrequal}{\testiii}{\DDD}{T}{F}}
將會回歸T
,而其穩健性\ifstrequal
對於其發揮作用至關重要。
使用工作測試。