LaTeX 中几乎所有命令前面都带有反斜杠。数学环境中的上标和下标命令(分别为 ^ 和 _)是唯一的例外吗?
答案1
在 TeX 和 LaTeX 中,区分“命令”或“控制序列”与 TeX 特殊字符至关重要。一般来说,只有前者以反斜杠 ( \
) 字符开头。(但请参阅下面最后一段,了解不以反斜杠开头的命令示例。)
^
和_
只是 TeX 特殊字符的两个例子。其他字符包括\
(反斜杠)、{
、}
、$
(“数学移位”)、&
、#
和%
(注释字符)。从 TeX 和 LaTeX 的角度来看,这些字符之所以“特殊”,是因为它们各自都有特定的特殊类别代码,或简称为 catcode。如果需要排版某个特殊 catcode 字符,则适用各种规则。例如,要排版一个 & 号、井号或百分号字符,必须在相应符号前加上反斜杠字符,即分别输入 、 和 。\&
要\#
在\%
文本模式下排版反斜杠符号,必须将其输入为“ \textbackslash
”或“ \string\
”。(后一种方法还需要T1
字体编码——它不适用于OT1
。使用后一种方法,\string\
如果目标是生成单个反斜杠字符,则后面需要一个空格;可能出现的不良副作用是在反斜杠字符后输出一个空格。相反,输入 会\string\hello
创建\hello
,而没有空格。)在数学模式下,可以通过输入 或 来输出反斜杠字符\backslash
,\setminus
具体取决于预期含义: 的数学状态为\backslash
“ord”(普通),而 的数学状态\setminus
为“bin”(二进制)。
如果有“特殊”的 catcode,那么也一定有“非特殊”的 catcode,对吧?事实确实如此。主要的非特殊 catcode 保留给字母(例如,a
至z
和A
至Z
),空格字符, 和“其他”字符(例如数字、标点符号、撇号、、、、"
和)。非特殊 catcode 的字符可以直接输入,即它们不需要以@
任何特殊字符作为前缀。行尾字符、“(
忽略”字符和“无效”字符也由非特殊 catcode 标识。)
-
/
最后,有一个 catcode活跃角色。“活动”字符是执行以下任一操作的命令的示例不是以反斜杠开头。在大多数 TeX 安装中, (“波浪号”) 的 catcode~
是“active”; 的主要用途~
是在两个单词之间插入一个不可中断的空格。要直接排版波浪号,必须像\~{}
在文本模式和\tilde{}
数学模式中一样输入它。据我所知,独立的波浪号在一般的印刷应用程序中并不常见。(我认为排版 URL 字符串是一种特殊的应用程序。)波浪号经常作为变音符号或“重音符号”出现,例如\~n
在Espa\~na
和中$\tilde{z}$
。另一个例子:如果babel
包使用选项 加载,某些标点符号(例如和)french
的 catcode将从“其他”更改为“活动”。此更改有助于为这些标点符号实现法语印刷实践。:
;
答案2
以下是从 TeX(具体来说是 Knuth TeX)程序内部的角度给出的答案。不需要知道以下任何一种都只是使用 TeX;这只是在您好奇其内部工作原理时才适用。
胃发出“指令”
TeX 程序的“主要”部分(经过一些初始化等)基本上是主循环(在源代码中调用main_control
)。代码的结构有点像下面的伪代码:
def main_control():
while True:
get_x_token # Sets `cur_cmd` and `cur_chr`.
# Now perform some action based on `mode` and `cur_cmd`...
# ... this action may use the value of `cur_chr`.
这个主控制程序就是 Knuth 在手册中描述的(TeXbook) 作为 TeX 的“胃”:它饥渴地等待着从 TeX 的“嘴” (上图) 传递给它的标记 (命令及其细节) get_x_token
。
因此从 TeX 的核心角度来看,一切到达它的是一个命令:例如,字母“e”作为命令“letter”(= cur_chr
101)传递到胃中。对于这个“letter”命令,相应的操作(如果 TeX 处于水平模式)只是“将此字符附加到当前字体中的当前 hlist”。
这里有一些常见的“命令”(及其大多不相关的内部代码),在什么情况下 TeX 的胃会收到这些命令,以及采取的相应操作:
- 信(11):当您输入被视为字母的字符时,TeX 的胃会获取此命令(默认情况下:A..Z、a..z)。操作(在水平模式下)是将该字符附加到当前 hlist。
- 其他字符(12):当您输入字符(例如,默认情况下)
"'()*+,-./0123456789:;<=>?@[]|
或反引号时,TeX 的胃会获取此命令。操作(在水平模式下)是将该字符附加到当前 hlist。 - 垫片(10):当您输入空格 (ASCII 32) 或制表符 (ASCII 9) 等字符时,TeX 的胃会获取此命令。操作是附加正常的单词间粘连或更大的粘连,具体取决于 space_factor(等)。
- 跳过(26):当您输入
\hskip
或\hfil
或类似的东西时,TeX 的胃会收到此命令。操作是扫描(如果需要),然后附加相应的胶水。 - 分配整数
\tolerance
(73):当您输入某些命令(如或 )时,TeX 的胃会收到此命令\day
。操作是调用一个名为 的内部过程prefixed_command
(在本例中,它将扫描一个值以查找相应的整数并分配该值)。 - 定义(97): 当你输入
\def
或\edef
或\xdef
或 时,TeX 的胃会收到此命令\gdef
。操作是调用一个名为的内部过程prefixed_command
(在本例中,它将扫描控制序列名称,然后是参数,然后是定义标记列表,并赋予该含义)。 - 左括号(1)(开始组):当您输入时,TeX 的胃会获取此命令(默认情况下)
{
。操作是开始新的保存级别。 - 数学移位(3):当您输入时,TeX 的胃会获取此命令(默认情况下)
$
。操作是进入或适当退出数学模式。 - sup_mark(7):TeX 的胃会在您输入时获取此命令(默认情况下)
^
。如果不在数学模式下,则操作是打印错误和insert_dollar_sign
(作为错误恢复),如果在数学模式下,则操作是调用sub_sup
(处理下标和上标)。 - par_end
\par
(13):TeX 的胃会在每个段落(或空白行)末尾获取此命令。 - 扩大(59):留给 TeX 的扩展,包括一些已实现的 TeX 内置功能喜欢扩展只是为了说明。操作是调用
do_extension
。 - 输出参数(5)(输出一个参数):当 TeX 的胃在标记列表中遇到您输入
#1
或 ... 或 时它所放置在那里的内容时,它会获取此命令#9
。 - 放松(0): 当你输入 时,TeX 的胃可能会收到此命令
\relax
。操作是不执行任何操作。
大约有 100 条命令可以进入 TeX 的胃口;eTeX、pdfTeX、XeTeX 或 LuaTeX 等 TeX 扩展有更多命令。其中一些命令(如“letter”)出现的频率非常高,以至于 TeX 将其视为经过更深入优化的“主循环”的一部分。
嘴巴“发号施令”
以上都是关于 TeX 的“胃”(主控制循环和语义例程/动作程序)的内容。但 TeX 的“嘴”(扫描例程)也同样有趣。在它向胃发出命令之前,那里发生了很多事情。
请注意,在上面,我说其中一些命令是由单个字符输入触发的,并且经常提到“默认情况下”。这是因为 TeX 有一个概念类别代码。共有 16 个,您可以在第 37 页阅读详细信息TeXbook或者这个网站上的许多问题,例如类别代码是什么?。我就不重复了,只举几个例子:
当 TeX 的嘴巴看到 catcode 为 11(字母)的字符时,它会向胃部发送命令“字母”(也是 11)。
当 TeX 的嘴巴看到 catcode 为 12(其他字符)的字符时,它会向胃部发送命令“other_char”(也是 12)。
当 TeX 的嘴巴看到 catcode 为 1(组开头)的字符时,它会向胃部发送命令“left_brace”(也是 1)。
同样地,对于 catcode 2 (组结束/“right_brace”)、catcode 3 (数学移位/“math_shift”)、catcode 4 (对齐制表符/“tab_mark”)、catcode 7 (上标/“sub_mark”)、catcode 8 (下标/“sub_mark”)、catcode 10 (空格/“spacer”),其中包括问题中提到的^
和_
。
但!
当 TeX 的嘴巴看到 catcode 为 14 的字符(
%
默认情况下为注释,类似)时,它不会立即向胃部发送任何内容,而只是跳到行尾——当它遇到真实命令时才会发送命令。当 TeX 的嘴巴看到 catcode 为 13(活动字符,默认情况下)的字符时
~
,它会查找该活动字符的含义,并相应地执行宏调用或扩展等。当 TeX 的嘴巴看到 catcode 为 0 的字符(转义字符,默认为反斜杠)时,它会扫描控制序列(基本上是单个非字母或字母序列),然后在哈希表中查找该控制序列以找出其含义,然后说“未定义的控制序列”或扩展它或......
嘴里会发生很多事情,例如条件语句\if
,或宏调用(任何用\def
或类似 定义的宏),或用 打开文件\input
,或类似 的事情\expandafter
。只有当所有这些“咀嚼”完成并且有“真正的”命令时,食物才会到达胃里。
概括
从用户从这个角度来看,TeX 已经
- “命令” 比如
\hskip
或\llap
, - 像主动角色
~
(也可以称为命令) - 特殊 catcode 字符,如
$
或^
或_
(通常不称为命令),以及 - 常见的 catcode(“字母”或“其他字符”)字符,如
e
或5
(几乎从不称为命令)。
从内部的看法,
- 角色有 catcode,
- 在此基础上,嘴巴可能会做进一步的扫描或扩展(在反斜杠或类似 的活动字符的情况下
~
), - 并根据得到的结果继续进行扩展(就像
\llap
是扩展为 的宏一样\hbox to\z@{\hss#1}
), - 最后向胃部发出命令(例如,
\llap
导致make_box
命令被传递), - 这些“命令”不仅包括“hskip”(对应于用户可能认为的命令
\hskip
),还包括“math_shift”和“sup_mark”,甚至“other_char”和“letter”(通常由单个输入字符组成), - 但这些“命令”不是包括诸如
\input
或\if
或\string
您可能考虑的命令之类的内容。
答案3
LaTeX 可以打印哪些字符具有非文字含义:
\makeatletter
\def\do#1{\ifnum\catcode\string`#1=12 \else
\message{\expandafter\@gobble\string#1}\fi}
\typeout{}\message{Chars:}%
\do\!\do\"\do\#\do\$\do\%\do\&\do\'\do\(\do\)\do\*\do\+\do\,%
\do\-\do\.\do\/\do\:\do\;\do\<\do\=\do\>\do\?\do\@\do\[\do\\%
\do\]\do\^\do\_\do\`\do\{\do\|\do\}\do\~%
\typeout{}%
\@@end
它打印:
Chars: # $ % & @ \ ^ _ { } ~
如果我们重新运行它
\documentclass{article}
\usepackage[french]{babel}
\begin{document}
添加后,它会打印更多内容:
Chars: ! # $ % & : ; ? @ \ ^ _ { } ~
我在 TeX Live 2015 和 2018 中尝试过这个(并且有效),使用乳胶,pdflatex和路拉泰克斯。