我对 TeX 中的注释、换行符和 s 的交互方式感到困惑\par
。请考虑以下内容:
ab
a b
a
b
a%
b
a
%
b
a
b
a%
b
产生输出
ab
a b
a b
ab
a b
a
b
a
b
我一直认为注释会“消耗”下一个换行符,所以我会预料到
a%
b
产生与
a
b
但又有所不同。这是为什么呢?
答案1
当 TeX 读取你的文件时,它会维护一个state
可以是以下三者之一的文件:
状态否(对于
new_line
):这是 TeX 从输入中每一行的开头开始的状态。状态米(对于
mid_line
):这是最常见的状态状态年代(对于
skip_blanks
):这与状态 M 类似,只是空白被忽略。
除其他事项外(请参阅更多详细信息TeX 主题 2.5 节以及第 46-47 页TeXbook或get_next
程序第 343 条及以后在 TeX 程序中),一些相关的交互如下:
在州内时否,
空格(catcode 10)将被忽略[§345](因此:每行的前导空格将被忽略),
行尾字符(catcode 5)产生一个
\par
标记 [§347→§351]注释字符(catcode 14)“结束该行”,即导致该行的其余部分(包括行尾字符)被忽略,因此(除非文件结束)TeX 将从下一行再次以状态 N 开始 [§347→§350]
大多数其他字符(字母等)将导致进入状态 M [§347]
在州内时米,
空格(类别码 10)产生空格标记并进入状态 S [§347→§349]
行尾字符(catcode 5)导致空格标记,并且(除非文件结束)TeX 将从下一行再次以状态 N 开始 [§347→§348]
注释字符(catcode 14)如上所述“结束该行”,即导致该行的其余部分(包括行尾字符)被忽略,因此(除非文件结束)TeX 将从下一行再次以状态 N 开始 [§347→§350]
在州内时年代,
空格(catcode 10)将被忽略[§345]
行尾字符(catcode 5)与上述一样“结束该行”,因此(除非文件结束)TeX 将从下一行再次以状态 N 开始 [§347→§350]
注释字符(catcode 14)与上述一样“结束该行”,因此(除非文件结束)TeX 将从下一行再次以状态 N 开始 [§347→§350]
(稍后添加):如果太长,可能的总结是:
首先想象一下,输入文件中的所有行都已删除所有前导空格,以便每行都是空的或以非空格字符开头。
遇到注释字符会将您“传送”到下一行的开头(这样就不会遇到行尾)。
当 TeX 位于行首并遇到行末时 —— 换句话说,如果该行(删除前导空格后)为空 —— 这将产生一个
\par
标记。否则,行尾相当于空格。
连续的空格相当于一个空格。
因此,让我们看一下所有 7 个示例:
ab
— 上面的输出产生了“ab”;没有什么有趣的事情发生。
a b
— 上面的输出产生了“ab”:看到空格后,TeX 进入状态 S,因此a b
也会产生相同的输出。
a
b
— 上面的代码在输出中产生了“ab”:当看到行尾时,会发出一个空格(上面列表中的 2.2)。请注意
a
b
也会产生相同的“ab”。
a%
b
— 上述代码在输出中产生“ab”:当%
看到 时,TeX 结束该行并进入状态 N(然后当b
看到 时进入状态 M),就像ab
在同一行中看到一样。同样,第二行上的前导空格将仍然结果为“ab”。
a
%
b
a
— 上述代码在输出中产生了“ab”:当看到行尾(在 之后)时,会生成一个空格并且 TeX 进入状态 N,然后当在第二行时,TeX 会忽略该行的其余部分(包括行尾),并且在第三行看到%
时再次处于状态 N。b
a
b
— 以上内容在输出中产生了两个段落:当看到行尾时(在 之后a
),TeX 进入状态 N,然后当它在状态 N 中看到另一个行尾时,它会生成一个\par
标记并从状态 N 中的第三行开始,然后看到b
。
a%
b
— 以上内容还会在输出中产生两个段落:当%
看到时,TeX 会丢弃该行的其余部分并从状态 N 中的第二行开始。现在它看到一个行尾(处于状态 N),从而生成一个\par
标记,之后 TeX 位于第三行并被b
看到。
答案2
请注意,空白行上的空格不会干扰解释\par
,因此规则并不像使用连续的换行符那么简单。这是因为 TeX 会忽略行首的空格。
实际规则是,TeX\par
在遇到行尾时生成标记,同时仍然忽略行上的前导空格。这会导致两个后果:\par
即使第一个行尾被埋在注释中,也会生成标记;n连续的换行符(可能混入空格)产生n-1 个\par
代币,不是n/2.
答案3
作为对其他技术答案的补充,我将补充我的想法。你似乎认为%
“消耗下一个换行符”。
这不是看待这个问题的最佳方式。在 TeX 中终点线字符。是的,字符 10 的 ASCII 名称是“换行符”或“换行符”,字符 13 的 ASCII 名称是“回车符”。
然而 TeX 采用了不同的方法。在编写 TeX 时,操作系统对于文本文件中“记录结束”的定义有着截然不同的看法。
有些使用“换行符”,有些使用“回车符”,有些使用两者以任意顺序组合,有些则什么都没有(它们有固定长度的记录,用字符 0,“null”)填充空白。
最后一种类型是类别代码 9(忽略)的原因:这里是摘录自plain.tex
,为清楚起见,标有行号:
24 % We had to define the \catcodes right away, before the message line,
25 % since \message uses the { and } characters.
26 % When INITEX (the TeX initializer) starts up,
27 % it has defined the following \catcode values:
28 % \catcode`\^^@=9 % ascii null is ignored
29 % \catcode`\^^M=5 % ascii return is end-line
30 % \catcode`\\=0 % backslash is TeX escape character
31 % \catcode`\%=14 % percent sign is comment character
32 % \catcode`\ =10 % ascii space is blank space
33 % \catcode`\^^?=15 % ascii delete is invalid
34 % \catcode`\A=11 ... \catcode`\Z=11 % uppercase letters
35 % \catcode`\a=11 ... \catcode`\z=11 % lowercase letters
36 % all others are type 12 (other)
如你所见,第 29 行表示终点线该符号`\^^M
表示“字符编号 13,因为M
ASCII 为 77,且 77 − 64 = 13。
由于操作系统曾经有过(现在仍然有)这些不同的想法,TeX 将向程序宣布记录结束信号的任务留给了特定系统的实现者。1
当 TeX 读取一条记录(换句话说是一行)时,它会丢弃记录结束信号(如果操作系统使用它的话)以及它前面的空格和行上它后面的内容。然后用与当前值\endlinechar
(默认值 13)相对应的字符替换它。
请注意,到目前为止,尚未发生转换为标记的过程。这发生在读入整行之后。如果在标记化过程中,TeX 发现类别代码为 14(注释)的字符,它会丢弃该行上剩余的内容并切换到下一个。
这状态其他答案中描述的与标记化阶段有关。
只要您改变思维方式即可%
:它会占用当前行。\par
无论前面是什么,空白行都会生成一个标记。空白行是仅包含类别代码 10(空格或制表符)或 9 的字符的行,直到找到类别代码 5 的字符。
例如,以下代码将只产生一段落:
\endlinechar`a
bc
ef
\end%
输出将是包含的单行bcaaefa
,因为根据上述定义,没有空行。
顺便说一句,最后一个%
是必须的,否则 TeX 不会再说\end
未定义。实际上未定义的控制序列是\enda
,但 TeX 永远不会显示当前的\endlinechar
。
脚注。
1 TeX Live 实现根据在输入文件开头找到的内容识别最常见的记录结束信号,无论是换行符(Unix)、回车符(旧版 macOS)还是回车符/换行符的组合(旧版 DOS)。