新行和 TeX:^^J 和 ^^M 之间的区别

新行和 TeX:^^J 和 ^^M 之间的区别

在下列情况下,TeX 的新行是什么:

  1. 从文件读取时。
  2. 写入文件时。
  3. 读完一个%字之后。
  4. 在一个\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

  1. 我认为,读取文件时行尾的定义是根据您运行的操作系统进行硬编码的。行尾由编号为 的字符表示\endlinechar
  2. 在写入时,数字为的字符\newlinechar将触发行尾。同样,输出文件中的确切结果是硬编码的,具体取决于您的操作系统。
  3. 见#1。
  4. 通常,参数\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\nWindows 上使用,但我尚未验证这一点。

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}这样做,将会有\input2 条单独的线路AB (这通常是您所需要的。)

不管您的操作系统使用什么来界定行尾,如果您这样做了等等,\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标记替换。

相关内容