命令名称由一系列字母(直到并排除第一个非字母)或单个非字母组成。
以字母结尾的命令名称(当然包括由单个字母组成的命令名称,例如\S
和\P
)将占用其后的所有空格。(例如 编译\P␣␣,H
。)
那么由单个非字母组成的命令名称怎么样:其中哪些会占用后续空格? H\$H
和H\$␣H
产生不同的输出(例如%
和&
也是如此)。虽然产生空格的命令\,
不会占用空格,但产生空格的命令\␣
似乎会占用所有后续空格。(H\␣H
和H\␣␣H
和H\␣␣␣H
都产生相同的输出。H \␣H
不同;请参阅下一段。)
了解 TeX 的行为将解释为什么例如A\,B
、A␣\,B
/A\,␣B
会A␣\,␣B
产生不同的结果(在文本模式下);如果用户不知道发生了什么,并且天真地(但可以理解)假设此类间距命令会吃掉它们周围的所有空格,那么他或她可能会遇到意外情况。(实际上,只有少数命令似乎会吃掉前面的空格,尽管这种行为是可能的:让您的宏以 开头\unskip
。)
解答指南:
- 最简洁的摘要(≈“仅
\␣
”):约瑟夫·赖特的回答[如果不是 Heiko 的回答,我会接受这个] - 所有细节(关于空的(!)命令名称有一个有趣的细节):Heiko Oberdiek 的回答
- 明显的例外(7 个标准的单字母、重音命令和
\\
):Mico 的回答
答案1
摘自“The TeXbook”:
如果 TeX 在任何状态下看到转义字符(类别 0),它会按如下方式扫描整个控制序列名称。(a)如果行中没有其他字符,则名称为空(如
\csname\endcsname
)。否则(b)如果下一个字符不属于类别 11(字母),则名称由该单个符号组成。否则(c)名称由以当前字母开头并在第一个非字母之前或行末结束的所有字母组成。此名称将成为控制序列标记。TeX 进入状态年代在情况 (c) 中,或在情况 (b) 中,对于类别 10(空格)的字符 [阅读:“在情况 (b) 中,如果单个符号属于类别 10(空格)”];否则 TeX 进入状态米。
状态年代是行首,空格被忽略;状态米位于线的中间。
如果名称完全由字母组成,则长度无关紧要,一个或多个字母。然后 TeX 会忽略行首的空格。命令 的情况也是如此\␣
。命令本身设置一个空格,但后面的空格会被忽略。
行尾的反斜杠:
如果 TeX 读取一行,它会删除行尾字符(回车符和/或换行符)以及最右端的所有空格字符(即,任何立即出现的此类字符)前行尾字符)。然后插入由 配置的字符\endlinechar
,除非该字符被抑制(例如,它具有负值)。摘自“The TeXbook”:
TeX 会删除输入行右端出现的任何 ⟨space⟩ 字符(编号 32)。然后,它会在行的右端插入一个 ⟨return⟩ 字符(编号 13),但它不会在
I
错误恢复期间插入的行尾放置任何其他内容。请注意,⟨return⟩ 被视为行中实际存在的字符;您可以通过更改此 catcode 来获得特殊效果。...
每行末尾插入的特殊字符不一定是 ⟨return⟩;TeX 实际上插入了一个名为 的整数参数的当前值
\endlinechar
,该值通常等于 13,但可以像任何其他参数一样更改。如果 的值为\endlinechar
负数或大于 255,则不会附加任何字符,效果就像每行都以 结尾%
(即以注释字符结尾)。
注意:LuaTeX 对 的值有限制\endlinechar
,其上限为 127,大于该值会引发错误! Invalid \endlinechar
。
在 LaTeX 中,行尾字符为^^M
(字符代码 13,0x0D),属于类别 5(行尾)。如果 TeX 处于状态米,这个行尾字符会被转换成空格[这是重点!],因此行尾的反斜杠通常变成\␣
。
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\begin{document}
\expandafter\def\csname\endcsname{<empty>}
\def\ {<space>}
\def\@{<at>}
[\
]
\begingroup
\endlinechar=-1
[\
]
\endgroup
\begingroup
\endlinechar=`@ %
[\
]%
\endgroup %
\end{document}
答案2
TeX 的一般规则在其他答案中有非常好的解释,即在由单个非字母组成的宏之后的空格(“非字母”是类别代码为 11 的任何内容)是不是“被吃掉”或被忽略。因此,\$ 50
和\$50
的排版不同。
乍一看,这条规则有一个例外:由一个单个非字母例如, \'
和\"
会吃掉宏和“重音符”(接收重音符、变音符号等的字母)之间的空格,也就是说,它们后面是直接跟着重音符,还是跟着一个或多个空格然后跟着重音符,这都无关紧要。也就是说,程序
\documentclass{article}
\begin{document}
\'e, \' e, \' e, \'{e}, \' {e}
\end{document}
产生五个相同的é
字符。
然而,上述一般规则的这种明显例外并不是因为这些宏构成了规则的真正例外,而是因为发生了其他事情。正如@egreg 在评论中指出的那样,产生重音的宏需要未限定参数,并且 TeX 在扫描此类参数时始终会忽略空格。(附言:未分隔的参数是 TeX 概念,而不是 LaTeX 概念:\def\abc#1{...}
是带有一个未分隔参数的宏。相反,\def\xyz#1+{...}
和\def\uvw&{...}
将第一个符号之前的所有内容+
以及第一和第二个&
符号之间的所有内容分别视为第一个参数。有关带有分隔和未分隔参数的宏的更多信息,请参阅 TeXbook 第 203 页底部的 double-dangerous-bend 项目。)
显然,在谈论命令后的空格被吃掉时,需要区分不接受参数的单非字母宏(例如,,,,)和接受无分隔参数的宏\#
。\$
\%
\&
查看我的计算机键盘,似乎有(至少)七个单非字母重音产生宏,它们采用无分隔参数:
\' \` \^ \" \~ \= \.
附录:除了这些重音产生宏之外,还有换行宏,\\
它也由一个非字母(反斜杠字符本身)组成。它采用两种类型的选修的参数:(i) 方括号内的内容,表示应插入的额外垂直空间量,以及 (ii) 单个*
符号。这些可选参数之间是否吃掉空格\\
取决于是否加载了amsmath
包——或者包,它修复了许多人认为是处理中的mathtools
一个小错误。amsmath
\\
答案3
TeX 有两种控制序列(转义符后跟一个或多个字符):
- A控制字:转义符后跟一个或多个“字母”
- A控制符号:转义字符,后跟一个非“字母”
其中转义字符是类别代码为 0 的任意字符,“字母”是类别代码为 11 的任意字符,非“字母”是类别代码不是 11 的任意字符。
后控制词,TeX 进入“跳过空格”状态:非正式地说,它“吃掉空格”。然而,在控制符号但有一个例外:控制空间 \␣
。
因此有两种情况:
- 控制字和控制空格:后面的空格会被跳过
- 控制空格以外的控制符号:不跳过任何空格
看TeX 按主题分类,第 2.5.2 节。
答案4
这很简单:没有任何控制符号会占用其后的空格。
然而,空间减少到一个前控制序列名称是在 的情况下形成的\␣
,这与输入中的任何空格序列等同于一个空格的说法是一致的。
嗯,这个可能虽然不是全部的事实,但却是一个很好的经验法则。