
考慮這個 MWE,修改自iftheelse 相等字串比較失敗:
\documentclass{article}
\edef\test{german\relax}
\edef\curentry{\string german\relax}
\typeout{test: \meaning\test, curentry: \meaning\curentry}
\ifx\curentry\test
\typeout{ equal}
\else
\typeout{ unequal}
\fi
\begin{document}
\end{document}
如果您使用 編譯它pdflatex test.tex
,您將在終端中看到以下輸出:
test: macro:->german\relax , curentry: macro:->german\relax
unequal
現在,連結的帖子解釋了為什麼會出現這種情況:
發生的情況是 \string 應用於它看到的第一個標記,在本例中是 g。比較兩個結果,它們不一樣:一個有 1 個非字母,然後有 5 個字母,第二個有 6 個字母。
但是,假設我嘗試在一個套件中檢查某些情況,但我並不真正知道巨集是如何定義的。所以我決定使用\typeout
宏\meaning
- 然後我得到了完全一樣列印內容,但條件仍然失敗。遇到這種情況我該如何除錯呢?
換句話說,是否有某種我可以使用的函數(類似於在 Latex 中產生一個 catcode 表(使用 \typeout 到終端)?) 將為上述巨集輸出,例如:
% \typeoutComponents{\test}
g (catcode 11)
e (catcode 11)
r (catcode 11)
m (catcode 11)
a (catcode 11)
n (catcode 11)
\relax (catcode ?)
% \typeoutComponents{\curentry}
g (catcode 12)
e (catcode 11)
r (catcode 11)
m (catcode 11)
a (catcode 11)
n (catcode 11)
\relax (catcode ?)
……這樣我才有機會推論為什麼「字串」(宏)相等會失敗?
(順便說一句,一個子問題:巨集/命令/令牌/控制序列(即以 開頭的東西\
)是否可以有catcode?)
答案1
該命令\tl_analysis_show:N
執行您所要求的操作。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\checktokenbytoken}{sm}
{
\IfBooleanTF{#1}
{
\tl_show_analysis:n { #2 }
}
{
\tl_show_analysis:N #2
}
}
\ExplSyntaxOff
\edef\xgerman{\string german\relax}
\checktokenbytoken{\xgerman}
\checktokenbytoken*{german\relax}
你會在終端機上得到,
The token list \xgerman contains the tokens:
> g (the character g)
> e (the letter e)
> r (the letter r)
> m (the letter m)
> a (the letter a)
> n (the letter n)
> \relax (control sequence=\relax).
<recently read> }
l.19 \checktokenbytoken{\xgerman}
?
The token list contains the tokens:
> g (the letter g)
> e (the letter e)
> r (the letter r)
> m (the letter m)
> a (the letter a)
> n (the letter n)
> \relax (control sequence=\relax).
<recently read> }
l.20 \checktokenbytoken*{german\relax}
(對於 TeX Live 2017 之前的版本,您還需要\usepackage{l3tl-analysis}
才能\usepackage{xparse}
使其正常工作,並且\tl_show_analysis:N
現已棄用)
答案2
我的解決方案不需要任何外部套件。該\showcat\macro
已實施。後
\def\test{ger{$##m}a~n \relax \foo}
\edef\curentry{\string german \relax}
\showcat\test
\showcat\curentry
我們得到結果:
\test ->
the letter g (catcode 11)
the letter e (catcode 11)
the letter r (catcode 11)
begin-group character { (catcode 1)
math shift character $ (catcode 3)
macro parameter character # (catcode 6)
the letter m (catcode 11)
end-group character } (catcode 2)
the letter a (catcode 11)
the token ~ (catcode 13)
the letter n (catcode 11)
blank space (catcode 10)
the token \relax (catcode 16)
the token \foo (catcode 16)
\curentry ->
the character g (catcode 12)
the letter e (catcode 11)
the letter r (catcode 11)
the letter m (catcode 11)
the letter a (catcode 11)
the letter n (catcode 11)
blank space (catcode 10)
the token \relax (catcode 16)
以及實施:
\def\showcat#1{\immediate\write16{\string#1 -> }\expandafter\showcatA#1\showcatA}
\def\showcatA{\futurelet\tmp\showcatB}
\def\showcatB{\let\next=\showcatE
\ifx\tmp\bgroup \let\next=\showcatC \fi
\ifx\tmp\egroup \let\next=\showcatC \fi
\expandafter\ifx\space\tmp \let\next=\showcatC \fi
\ifx\tmp\showcatA \let\next=\showcatF \fi
\next
}
\def\showcatC{\afterassignment\showcatD \let\tmp= }
\def\showcatD{\showcatE\tmp}
\def\showcatE#1{\edef\next{\string#1}%
\immediate\write16{\space\space
\ifnum\showcatG<13 \meaningtmp \else the token \next
\fi \space (catcode \showcatG)}%
\showcatA
}
\def\meaningtmp{\meaning\tmp}
\def\showcatF#1{}
\def\showcatG{\showcatH\bgroup1\showcatH\egroup2\showcatH$3\showcatH&4%
\showcatH##6\showcatH^7\showcatH_8\showcatH{ }{10}%
\showcatH A{11}\showcatH/{12}\showcatH~{13}16}
\def\showcatH#1#2{\ifcat\noexpand\tmp\noexpand#1#2\expandafter\showcatI\fi}
\def\showcatI#116{}
當然,類別 0、5、9、14、15 的標記永遠不會出現在宏體中。為了\showcatG
在\ifnum
測試中簡單使用,控制序列(沒有類別的標記)在這裡表示為類別 16。