在下列情况下,TeX 的新行是什么:
- 从文件读取时。
- 写入文件时。
- 读完一个
%
字之后。 - 在一个
\scantokens
。
我特别询问是因为以下代码仅排版A
:
\documentclass{minimal}
\begin{document}
\catcode`\%=12
\def\foo{\scantokens{A%
B}}
\show\foo
\catcode`\%=14
\foo
\end{document}
所以我的主要问题是:如何%
知道何时停止吞噬字符?
编辑:添加两行
\catcode`\^^M=12
\newlinechar`\^^M
在的定义之前\foo
是有指导意义的:那么定义实际上包含换行符,并且注释会在我们期望的地方停止吞噬。
EDIT2:pdflatex
集合\newlinechar`\^^J
和\endlinechar`\^^M
(请参阅下面 Harald 的简明回答以了解这些是什么)。
答案1
- 我认为,读取文件时行尾的定义是根据您运行的操作系统进行硬编码的。行尾由编号为 的字符表示
\endlinechar
。 - 在写入时,数字为的字符
\newlinechar
将触发行尾。同样,输出文件中的确切结果是硬编码的,具体取决于您的操作系统。 - 见#1。
- 通常,参数
\scantokens
被视为单行。因此,参数 中的百分号\scantokens
将结束此参数的输入。但是,任何出现的字符(其数字为)都\newlinechar
将用于将参数拆分为多行。
为了将所有这些想法结合起来,考虑纯 TeX 文件
\newlinechar=2
{\catcode`\%=12
\gdef\foo{\scantokens{abc%xyz^^Bdef}}}%
\endlinechar=`X
\foo%
\bye%
这将排版文本“abcdefX”。
(已编辑考虑到我从评论中了解到的关于#4的信息。)
答案2
所以你问了几个问题,但让我先回答你的主要问题。
这里发生的情况是,当解析 的定义时\foo
,它与
\def\foo{\scantokens{A%\par B}}
现在\scantokens
执行时,就像读到以下行
A%\par B
来自当前 catcodes 有效的文件。由于您将其重置%
为注释,因此\par B
将被忽略。
对于您的其他问题,TeX 的单独安装可以确定在读取和写入文件时将什么视为换行符。如果我没记错的话,\n
、\r
、\r\n
和\n\r
被视为输入的换行符,至少这是我最近阅读 pdfTeX 源代码时记得的。对于输出(即写入文件),我怀疑它\n
在 *NIX 和\r\n
Windows 上使用,但我尚未验证这一点。
TeX 从输入文件中读取一行文本后(开始对其进行标记之前),它会删除所有尾随空格字符(包括\r
和),\n
并附加\endlinechar
通常为的字符^^M
(即)。无论行中\r
是否有字符,都会发生这种情况。当 TeX在其输入中遇到字符时(请注意,没有注释%
%
令牌),它会忽略该行的其余部分,包括尾随的\r
。
据我所知,^^J
(即\n
)在大多数情况下并不特殊,除非它经常\newlinechar
用作中的用法\write
。
我忘了\scantokens
。它实际上被视为来自文件的输入行,包括\endlinechar
每行末尾的。有关此内容的简单示例,请尝试
\endlinechar`X %
\scantokens{A}%
\bye%
(X 后面的空格是必需的,因为 TeX 在那里寻找可选空格。)每一行都以百分比结尾,但输出显示AX
因为\scantokens
已插入该字符。
答案3
这里的重点是:
\scantokens
表现得“像”\write
。\write
^^J
当遇到( )时写入物理换行符\newlinechar
。
因此,如果您\scantokens {A ^^J B}
这样做,将会有\input
2 条单独的线路A
和B
(这通常是您所需要的。)
不管您的操作系统使用什么来界定行尾,如果您这样做了等等,\scantokens {A ^^M B}
则不会如此。\scantokens {A \par B}
假设 ^^J 和 ^^M 在此处有“其他”类别代码。
附注:
默认情况下 (
\ExplSyntaxOn
区域外),如果你这样做\catcode `\^^M = \the \catcode `[ \relax \def \a { }
或者
\def \a {\ }
那么您将“看到”换行符总是“对应”于
^^M
(字符代码 13),而不是^^J
,如果您不知道确切的行为而只是“猜测”,这可能会导致混淆。(那是因为是 13。)
\endlinechar
例如在 UNIX 系统上,如果
\newlinechar
不是^^J
,则写入^^J
将仍然生成一个物理换行符;但是scantokens
不会将其视为物理换行符。Catcode 5(“行尾” catcode”)是完全不同的东西,它表示该 catcode 的两个连续标记应该被一个
\par
标记替换。