LaTeX 如何管理交叉引用?

LaTeX 如何管理交叉引用?

我正在创建包含各种参考、引文、索引、目录和其他链接元素的文档。LaTeX 如何知道如何正确地交叉引用页面,同时正确地格式化页面并保持页码正确?

Latex 如何知道插入页面引用不会修改所引用标签的页面?

例如,如果我在文档后面引用了某个部分,\ref{sec:bestsection}那么 LaTeX 必须稍后找出该部分\label{sec:bestsction}位于哪个页面,然后返回并将其插入到\ref第二次编译的位置(请参阅这个答案)。

但是,假设我有一个很大的文档,并且恰好sec:bestsection在第10230。另外,假设这个大页码恰好为文档增加了足够的空间,以至于将另一个单词推到了页面末尾。一件事导致另一件事,现在sec:bestsection在第10231

LaTeX 如何知道发生了这种情况并且不使用错误的页码?它是否总是假设 a\ref适合该行?

答案1

标题中问题的答案是“LaTeX没有知道”,至少不是完全知道。

LaTeX 如何管理交叉引用?

假设你有

As we shall see in section~\ref{sec!main-results}, ...

...[many pages later]...

\section{Main results}\label{sec!main-results}

We are now ready to prove the most important theorems.

看到的时候\label,页面\ref早已排版输出了:根本没办法“找回来修号”。

因此,这种方法不是“一次性正确获取所有交叉引用”,因为它需要在进行任何排版之前将整个文档保存在内存中。相反,LaTeX 在输出\label出现命令的页面时会立即写一条注释:在.aux文件中,你会发现类似

\newlabel{sec!main-results}{{3}{9}}

其中第一个数字是章节号,第二个数字是页码。只有在发送页面时才会写出注释,因为只有这样才能真正知道页码。请记住,TeX 总是会提前查看,并且只排版完整段落,然后再决定分页符。

在作业结束时,.aux文件被关闭并输入。此时\newlabel会获得一个适当的定义,其目的是检查标签是否在之前的运行中已知,在这种情况下,其中一个相关数字是否已更改。

此时你会看到如下警告

Label(s) may have changed. Rerun to get cross-references right

There were multiply-defined labels

Label `<label>' multiply defined

这应该是不言自明的。

在作业开始时,当 LaTeX 正在处理时\begin{document}.aux文件被输入并\newlabel获得不同的定义,这允许\ref{sec!main-results}\pageref{sec!main-results}打印正确的数字。但是什么数字?在上述情况下,即使您在运行之间添加了整个部分,部分编号也将是 3。只有在作业结束时,LaTeX 才会知道数字已更改,并且它会发出上面列出的第一个警告。

如果交叉引用未知,则??只会打印并发出有关已更改标签的警告。如果\ref\pageref命令引用尚未定义的标签,则会收到警告

There were undefined references

但是也

Reference `<label>' on page <page> undefined

它会告诉你,也许你拼错了标签。

我们应该关心交叉引用的大小吗?

我们应该关心参考文献使用的空间吗?其实不必。段落通常具有足够的灵活性,允许收缩或拉伸一行而不会对输出进行实质性修改。这并非万无一失,而且有一些巧妙编写的文档永远无法稳定的例子:每次运行 LaTeX 都会更改与标签关联的页码,因此它永远不会保持不变。但是,这种情况在真实文档中发生的几率非常小。

那么多次运行怎么样?

文档处理器(例如)latexmk能够查看.log文件中有关已更改标签或未定义引用的警告,并触发新运行以修复输出。但是,交叉引用在每个时间点是否正确并不那么重要:当您没有收到上述警告时,它们就是正确的。

那文件怎么办.aux

.aux文件还有其他几个用途:例如引用,但也用于其他管理任务。软件包(尤其是hyperref)可以通过扩展两个版本的语法来修改所做的注释\newlabel,但处理这个问题会太耗时。想法仍然是一样的。

.aux重要提示。从这个描述中可以清楚地看出,在运行之间保持文件的完整性是基本的。除非由于某些致命错误而损坏,否则通常不应删除此文件。不完整的注释可能会导致输入文件时出错:在此错误处中断 LaTeX 运行将保留相同的损坏文件,因此在下次运行时将再次出现相同的错误。在这种情况下,删除文件.aux是唯一的补救措施。没什么大不了的,它将花费一次新的 LaTeX 运行(可能两次)。但是,当然,.aux在运行结束时删除正确的文件将总是产生有关未定义引用的错误。

最后,有一个开关可以让 LaTeX 不触及它写出的任何文件:如果你\nofiles在序言中添加,则.aux文件和用于目录和类似列表的文件将仅被输入而不会被重写。这是过去的遗留问题,当时即使写入文件或只是保持某些文件打开也会导致延迟,因此当人们确定交叉引用和列表是正确的时候,添加\nofiles可以节省一些运行时间。如今,开销非常小,以至于这种技巧几乎毫无用处。

答案2

它将所有引用的页码写入辅助文件。请注意,在第一次运行时,如果没有辅助文件,它会改为输入 ??。在以后的运行中,它会首先读取辅助文件。然后,当它记录页码时,它会将页码与上次运行中写入辅助文件的页码进行比较。如果任何引用不同,它会在运行结束时发出警告。

但可以想象,这个过程永远不会结束。随着页码位数的增加,可以想象(勉强)段落将变成一行更短,这是由于段落构建算法的工作方式。这反过来又会将引用的页面向后移动一页,从而再次缩短页码。但我认为你必须非常努力才能想出一个例子。

如果您使用罗马数字来编号页面,则会更容易一些:现在后面的页码可以使用更短的数字,这更有可能将段落缩短一行。

答案3

这就是为什么你需要运行 latex 两到三次(或更多次)的原因,如果你运行 latexmyfile.tex然后查看myfile.aux,你会看到所有的交叉引用信息。因此,在第一次运行时,引用是公正的,?但之后它使用上次写出的值。在运行结束时,latex 会进行一致性检查,以确保它写入的值与读入的值相同,如果它们不同,它会发出“标签已更改,重新运行 LaTeX”警告。

相关内容