我可以在各个章节之间重复使用章节标签吗?

我可以在各个章节之间重复使用章节标签吗?

我正在格式化一个包含许多章节的长文档。大多数章节包含一些通用部分(例如“简介”、“结果”......),其中大多数都已贴上相应的标签(例如\label{sec:intro}\label{sec:results}。这对于逐章而言没有问题,但是当我将它们放在一起时,这意味着某些标签将使用多次(例如,可能有来自sec:intro五个不同章节的五个标签。)

我可以使用这些标签而不重命名它们吗?LaTeX 是否足够智能,知道.tex第 2 章文件中\ref{sec:intro}引用的是当前章节中的“简介”部分。

如果不是,首选的解决方案是什么?重命名所有标签似乎很笨重且不可靠。

答案1

正如 David Carlisle 所说,重命名你的标签。这可以通过使用流编辑器轻松完成,sed例如。

假设您有一个关于狮子的章节文件和一个关于斑马的章节文件;在这两个章节文件中,您都使用了您描述的标签约定,如下所示:

狮子.tex

\chapter{Lions}
\section{Intro}\label{sec:intro}
\section{Results}\label{sec:results}
Here's a reference to \ref{sec:intro} and \ref{sec:results}.

zerbras.tex

\chapter{Zebras}
\section{Intro}\label{sec:intro}
\section{Intro}\label{sec:intro}
\section{Results}\label{sec:results}
Here's a reference to \ref{sec:intro} and \ref{sec:results}.

您可以使用sed搜索和替换每个文件中的\label每个\ref文件,以便所有标签和引用都得到适当的更改

sed -i 's/\\\(label\|ref\){\([^}]*\)/\\\1{lions:\2/g' lions.tex
sed -i 's/\\\(label\|ref\){\([^}]*\)/\\\1{zebras:\2/g' zebras.tex

现在你的文件看起来如下

lions.tex(新)

\chapter{Lions}
\section{Intro}\label{lions:sec:intro}
\section{Results}\label{lions:sec:results}
Here's a reference to \ref{lions:sec:intro} and \ref{lions:sec:results}.

zebras.tex(新)

\chapter{Zebras}
\section{Intro}\label{zebras:sec:intro}
\section{Intro}\label{zebras:sec:intro}
\section{Results}\label{zebras:sec:results}

Here's a reference to \ref{zebras:sec:intro} and \ref{zebras:sec:results}.

理解\\\(label\|ref\){\([^}]*\)/\\\1{lions:\2/g

我使用的基本语法是s/old/new/g用“新”替换“旧”。g标志表示全局执行此操作。让我们将上述表达式分解为几个部分:

  • \\\(label\|ref\)匹配\label\ref并将结果存储到内存中,稍后用作\1。请注意,我们需要使用\转义特殊字符

  • {\([^}]*\)匹配里面的东西{...},但这样做非贪婪方式。这个正则表达式不能贪婪,这一点非常重要;如果贪婪,那么在操作表达式时Here's a reference to \ref{sec:intro} and \ref{sec:results}它将匹配

    sec:intro} 和 \ref{sec:results}

这并不是我们想要的!

  • \\\1{lions:\2是替换文本,使用\1\2作为已存储在内存中的匹配。

另外支持 cleveref

Cleveref 使用\cref\Cref

sed -i 's/\\\(label\|[Cc]\?ref\){\([^}]*\)/\\\1{lion:\2/g'

对目录中的所有文件运行此操作很有用,并且通过使用*.tex文件参数可以轻松完成,您的 shell(bash,等等)将扩展到所有文件。

答案2

手动本地化标签和引用可以使用某种前缀来完成,例如,sec:labelA如评论中所建议的那样。但这意味着必须更新所有出现的\label\ref\pageref使用这些前缀。

另一方面,使用 TeX 来自动化并不那么困难:

\documentclass{article}

\AtBeginDocument{%
\let\origref\ref
\let\origpageref\pageref
\let\origlabel\label
\newcommand\locallabels[1]{%
  \renewcommand\label[1]{\origlabel{#1##1}}%
  \renewcommand\ref[1]{\origref{#1##1}}%
  \renewcommand\pageref[1]{\origpageref{#1##1}}%
}}

\begin{document}
\section{A}\label{foo} 

test \ref{foo} on \pageref{foo} 

\locallabels{sec1:}

\newpage
\section{B}\label{foo} 

test \ref{foo} on \pageref{foo} 

\locallabels{}

\newpage
test \ref{foo} on \pageref{foo}  

\end{document}

基本上,这会保存这些命令的当前定义,然后在\locallabels调用时重新定义它们,以添加作为参数给出的前缀\locallabels

笔记

  • 定义应该放在 的最后面,\begin{document}以便在某些包修改命令时获取命令的最新定义。例如hypherref,使用 重新定义时,\AtBeginDocument我们必须执行相同的操作。
  • 如果使用类似扩展,则varioref此类包的命令将需要相同的处理。如果amsmath使用,则需要额外调整的命令称为\label@in@display,请参阅将自定义 \locallabels 命令与自定义 \eqref 命令结合使用
  • 当然,每次使用都\locallabels应该使用不同的前缀,除非希望两个区域共享标签,例如,\locallabels{}在示例中,返回到不使用前缀,因此选择了 A 部分的引用。
  • 如果需要\locallabels从外部引用范围内的标签,可以使用 来实现\origref{<prefix><label}

答案3

我写了一个脚本在我把论文装订成论文时,呃,我的意思是写论文时,sed 策略对我来说不太管用,因为我使用 cleveref 在同一命令中引用多个标签,例如\Cref{sec:experiments,sec:results}

使用示例:

python add_ref_suffix.py --suffix chp1 --files *.tex

效果:\Cref{sec:experiments,sec:results}变为\Cref{sec:experiments:chp1,sec:results:chp1},标签也相应改变。 没有什么特别的\Cref{};以​​ 结尾的任何东西ref都会改变,所以它应该适用于\ref\href\cref\autoref等。我选择添加后缀而不是添加前缀,因为我使用了一个可以自动完成引用的 sublime 插件,并且我更喜欢在自动完成时按引用类型进行索引。

相关内容