我目前正在阅读 TeXbook(第 6 次印刷,1986 年 3 月)。
在第 6 章中,Knuth 解释了\input story
可以用来加载/处理story.tex
。
然而,在前面的章节中,读者可以通过以下例子了解分组的重要性:
\centerline{This information should be {centered}.}
\centerline So should this.
这表明,只有后续符号正在\centerline
使用,因此对于第二个,\centerline
将S
居中,但o should this.
会在新行上,而不是居中。
所以我想知道为什么\input story
它有效(是的,我测试过)以及为什么它无效不得不 \input{story}
这正是我在 LaTeX 中习惯的。
这似乎是违反直觉的,因为第一次读到这篇文章时,我当时得到的信息是控制字 \input
应该采取下一步行动象征仅有的。
也许我遗漏了什么?
答案1
\centerline
是一个宏,在 中定义plain.tex
,\def\centerline#1{\line{\hss#1\hss}}
因此它接受一个参数。通常,参数将是一个单个标记(S
例如,是一个单个标记),除非这个标记是一个{
,在这种情况下,将接受一个{
...}
平衡的标记列表作为参数。
在 Plain TeX 中\input
是一个原语,因此其规则不同。原语将查找字符标记,并在第一个空格标记[1]处停止。在 LaTeX 中\input
是一个宏,但如果下一个标记不是{
,则它充当原语输入。如果下一个标记是{
,则\input
充当宏并获取文件名作为参数。
\centerline
您可以通过让它抓取输入行的其余部分来模拟这种情况:
\def\centerline{%
\begingroup
\catcode`\^^M=13
\centerlineaux}
\begingroup
\catcode`\^^M=13
\gdef\centerlineaux#1^^M{\endgroup\line{\hss#1\hss}}
\endgroup
\centerline This entire line is centered.
But this is not.
\bye
1有不同的实现\input
:Knuth\input
会扫描字符标记,直到找到非字符标记或空格。如果该标记是空格,则将其丢弃。找到的字符将作为文件名。
Web2C 实现(TeXLive 和 MiKTeX 使用它)允许\input
文件名中有空格,只要空格出现在两个 之间即可"
。
最后,在 TeXLive 2020 及以后的所有 TeX 引擎中(在此之前仅在 LuaTeX 中),如果基元后的下一个标记\input
是{
,则文件名将在括号之间被抓取(\input{story}
将输入)。由于这就是 Knuth 所说的“依赖于文件系统的更改”,因此这也story.tex
适用于。tex
答案2
\input
实际上是原始的,它们被定义为 TeX 核心的一部分,而不是基于其他宏构建的单独宏。如果您查看\input
和朋友的定义(在latex.ltx
):
\ifx\@@input\@undefined\let\@@input\input\fi
% <some other definitions>
\def\input{\@ifnextchar\bgroup\@iinput\@@input}
% <some other definitions>
\def\@iinput#1{%
\InputIfFileExists{#1}{}%
{\filename@parse\@curr@file
\edef\reserved@a{\noexpand\@missingfileerror
{\filename@area\filename@base}%
{\ifx\filename@ext\relax tex\else\filename@ext\fi}}%
\reserved@a}}
请注意,命令序列在加载 LaTeX 内核时\input
将 TeX 原始定义存储在内部。然后它(重新)定义为通过 有条件的。此条件检查您是否提供了左花括号(或)。如果是,它会调用 。当您使用时,情况就是这样\@@input
\input
\@ifnextchar
{
\bgroup
\@iinput
\input{story}
的定义\@iinput
意味着它接受一个强制参数,就像您使用的任何其他宏一样。从您最初的用例来看,这是有道理的。但是,为什么 的\input story
工作方式相同?为此,我们遵循\@ifnextchar
条件中的错误分支。也就是说,\@@input
。
由于是原语\@@input
的精确副本\input
,它将文件名读取为后面的非空字符串\input
。此过程的参考资料scan_file_name
在tex.web
。