通常情况下,文本中美元符号 ( ) 的 catcode$
是 3。但我发现
$
页眉和页脚中的catcode 为12,并且$
仍可用作数学移位。
例子:
\documentclass{article}
\makeatletter
\def\@oddfoot{\the\catcode`$, $a + b = c$\hfill}
\def\@oddhead{\the\catcode`$, $a + b = c$\hfill}
\makeatother
\begin{document}
\the\catcode`$, $a + b = c$\par
\catcode`$=12
\the\catcode`$, $a + b = c$
\end{document}
我目前的理解:
$
中的 catcode$a + b = c$
是从 的重新定义中获得的\@oddfoot/head
,这也许可以解释第二部分。- 但我仍然对第一部分感到困惑,正如问题标题所述。
答案1
首先,重新定义\@oddhead
和时生效的设置\@oddfoot
为 $ 3(下标表示 catcode)。在定义时,TeX 读取人物 \the\catcode`$, $a + b = c$\hfill
并将它们变成代币:
\the
\catcode
`
12 $
3 ,
12 10
$
3 a
11 10
+
12 10
b
11 10
=
12 10
c
11 $
3\hfill
(获取此标记列表的一个非常有用的工具是expl3
。\tl_analysis_show:N
)
这种标记化发生在定义时 catcode 设置在生效的情况下,即使 catcode 发生变化,TeX 也不会改变这一点。引用TeXBook(第 8 章,您输入的字符;重点是我的):
[...] 最好不要经常玩弄类别代码,因为你必须记住一旦字符成为 token,它们就永远不会改变其类别。
或者,举个例子,来自附录 D:
[...] 当第一次从文件中读取字符时,TeX 会在每个字符上标记类别。因此,如果
\verbatim
通过以下形式的构造来定义\long\def\verbatim#1{⟨something⟩}
,则参数在启动#1
时已转换为标记列表⟨something⟩
;\catcode
更改不会影响参数。
这就是通常所说的“冰冻的猫代码”并且,正如 Skillmon 在评论中所说,改变它的唯一方法是使用 ε-TeX 的\scantokens
。
现在回到您的文档,其中\@oddhead
和\@oddfoot
已经用 $ 3标记化,当文档开始时, 的 catcode$
仍然是 3,如您在第一个等式中看到的那样。然后您更改$
为 catcode 12 并编写另一个等式,该等式不再处于数学模式,因为$
不是 catcode 3。现在文档结束了。
TeX 知道您写了一些东西,但它仍然没有尝试将段落分成页面:到目前为止您写的所有内容都在等待\vbox
发送。当 LaTeX 看到时,\end{document}
它会开始准备最终的(在这种情况下只有)页面,其中包含您所写的内容。此准备工作的一部分是包含页眉和页脚,此时它使用\@oddhead
和\@oddfoot
。此时,$
根据您的定义查询的 catcode,它是 12,只是因为您更改了它。
页眉没有特殊的 catcode 设置(至少通常没有),但它不会尝试强制执行任何特定设置,因此将使用最后一个活动设置($ 12)。但是方程式仍将处于数学模式,因为标记化的\@oddhead
和\@oddfoot
有 $ 3。结论是:的 catcode$
不会被 LaTeX 的输出例程改变;你改变了它!
您可以通过将 catcode 改回来进行实验:
\the\catcode`$, $a + b = c$\par
\catcode`$=12
\the\catcode`$, $a + b = c$
\catcode`$=3
或者在组中进行更改:
\the\catcode`$, $a + b = c$\par
{\catcode`$=12
\the\catcode`$, $a + b = c$\par}
您将会看到设置恢复正常。
作为练习,尝试使用\scantokens
(在\catcode`$=12
之前使用\end{document}
):
\makeatletter
\def\@oddfoot{\the\catcode`$, \scantokens{$a + b = c$\hfill}}
\def\@oddhead{\scantokens{\the\catcode`$, $a + b = c$\hfill}}
\makeatother
(在运行 TeX 之前尝试猜测输出)