![生成持久且唯一的 ID(用于规范中的需求)](https://linux22.com/image/390415/%E7%94%9F%E6%88%90%E6%8C%81%E4%B9%85%E4%B8%94%E5%94%AF%E4%B8%80%E7%9A%84%20ID%EF%BC%88%E7%94%A8%E4%BA%8E%E8%A7%84%E8%8C%83%E4%B8%AD%E7%9A%84%E9%9C%80%E6%B1%82%EF%BC%89.png)
- 我希望拥有(可见的)ID执着的(也许英语里有比“持久”更好的词)独特的在文档中。
- 和执着的,我的意思是,如果我添加带有 ID 的其他内容,那么旧 ID 将保持不变(即使我删除了标准文件
aux
)。 - 目前我使用的是
\subparagraph
KOMA 书籍课程的级别。\subparagraph
数字作为ID。ID是独特的但不坚持。 - 背景:用例是规范中的ID标签要求。
你知道如何实现吗执着的和独特的ID?我想使用pdflatex并且(如果可能的话)坚持古玛级。我愿意接受建议!
PS:我不知道tags
该用哪一个来回答这个问题。
// 由于评论中的热烈讨论,因此更新
- 首先谢谢!
- 我对自己能处理的妥协没有清晰的认识/看法。到目前为止,我只有唯一的 ID,仅此而已。
- 我使用标题是因为这是一种获取唯一数字的懒惰方式,并且它们不会干扰其他内容(这是我最初的解决方案:\everypar 部分(或章节)命令不起作用)。
- 我对可能发生的事情很感兴趣。
- 如果这些解决方案造成一些限制,那么我愿意尝试。
\documentclass[parskip=full]{scrbook}
\usepackage{xcolor}
% Number \subparagraph
\setcounter{secnumdepth}{5}
% Add \subparagraph to TOC (not important for the MWE)
\setcounter{tocdepth}{5}
% Color \subparagraph
\addtokomafont{subparagraph}{\color{red}}
\begin{document}
\tableofcontents
\chapter{Chapter}
Test text. Test text. Test text.
\section{Section}
Test text. Test text. Test text.
\subsection{Subsection}
Test text. Test text. Test text.
\subsubsection{Subsubsection}
Test text. Test text. Test text.
\paragraph{Paragraph}
Test text. Test text. Test text.
\subparagraph{Subparagraph: Should have a Persistent and Unique ID / Number}
Test text. Test text. Test text.
\end{document}
答案1
“持久ID”、“唯一ID”——我仍然不清楚你真正想要的是什么。
哪些实例将创建这些 ID?
哪些实例将以何种方式使用这些 ID?
这些 ID 的用途/目的是什么?
机器/LaTeX 编译器是否会自动创建这些 ID?
如果这是您所追求的:
当使用这些 ID 时,除了 (La)TeX 程序本身之外,是否会有其他实例进行干预,需要知道这些 ID/需要知道到底要通过哪个 ID 来识别什么?(例如,这样的实例可以是提供/创建 (La)TeX 源代码的实例。;-))
如果是这样:该实例应该通过什么方式获取他/她需要的信息?
如果不是这样,那么似乎存在无需干预的例程,既可以创建 ID,又可以处理这些 ID 的所有使用情况。
看来,在任何情况下,在整个 LaTeX 运行过程中的持久性要求都意味着:
每次调用例程都会自动生成和使用以 ID 形式存在的、在整个 LaTeX 运行过程中都保持不变的信息,因此需要为未来的 LaTeX 运行留下额外的信息,这些例程可以在下一次 LaTeX 运行的每次调用中使用这些信息来检测该调用在当前 LaTeX 运行中留下的信息,而下一次 LaTeX 运行中所涉及的调用与当前 LaTeX 运行相对应。
因此,您需要为例程本身的调用使用唯一的、不变的标识符,并且您需要让 LaTeX 在所有 LaTeX 运行过程中保留这些唯一的、不变的标识符。
问题在于:
据我所知,在 LaTeX 运行期间保存 LaTeX 运行期间创建的信息片段的唯一方法是通过可在下一次 LaTeX 运行中读取的临时文件。当相关临时文件不复存在时,信息将丢失。
另一个问题是:
上面我已经提到,您需要为例程本身的单个调用使用唯一的、不变的标识符,并且您需要让 LaTeX 在整个 LaTeX 运行过程中保留这些标识符。
因此,您需要一种机制,用于在整个 LaTeX 运行过程中自动创建和保留 ID 生成例程的单个调用的唯一且不变的标识。
瞧:您将在底层面临最初的问题。
所以我认为在任何情况下都会有某种程度的识别,需要由提供 (La)TeX 源代码的实例提供唯一的不变的标识符。
这里我想到的是 LaTeX 2e 的交叉引用机制:
使用 LaTeX 2e 的- -cross-referencing-mechanism,提供 tex-source-code 的实例被要求为 cross-referencing-labels 提供唯一的名称。 如果该实例没有提供,LaTeX 2e 将通过警告抱怨标签被多次定义。 您可以在正在使用的终端/shell 的屏幕上以及 .log 文件中看到这些警告。 只要没有人在 tex-source-code 中更改 cross-referencing-labels 的这些名称,它们就会一直存在。\label{⟨name of referencing-label⟩}
\...ref{⟨name of referencing-label⟩}
在阅读了对该问题的评论后,似乎一个\label
--\ref
机制不仅提供引用命令来将文本短语(如页码和计数器值等)放入输出文件(pdf 文件),而且还提供引用命令来将表示引用标签本身名称的文本短语放入输出文件(pdf 文件)中,这可能就是您所需要的。
通常使用\label
--\ref
机制您只能获得页码和计数器值。
使用Heiko Oberdiek 的 zref 包您可以轻松增强\label
-\ref
机制,以便标签命令存储和引用命令传递其他信息。此类信息可以是引用标签本身的名称。
在下面的例子中我使用了Heiko Oberdiek 的 zref 包用于创建一个与命令\LabelWhoseNameCanBeShown
类似的命令\label
。不同之处在于,除了通过\ref
、\pageref
、\hyperref[...]{...}
等引用之外,它还可以通过命令 引用标签本身的名称\ReferNameOfLabelWhoseNameCanBeShown
。
\ReferNameOfLabelWhoseNameCanBeShown{⟨name of referencing-label⟩}
应采取如下行动:
⟨name of referencing-label⟩
如果通过定义/引入了 引用标签,则应(在第二次 LaTeX 运行中)将其作为文本短语传送到 .pdf 输出文件中。\LabelWhoseNameCanBeShown{⟨name of referencing-label⟩}
\ReferNameOfLabelWhoseNameCanBeShown
⟨name of referencing-label⟩
如果没有⟨name of referencing-label⟩
通过定义/引入引用标签,则应该发出错误消息和一些问号。\LabelWhoseNameCanBeShown{⟨name of referencing-label⟩}
\ReferNameOfLabelWhoseNameCanBeShown
\documentclass[a4paper]{article}
\usepackage{hyperref}
\usepackage{zref}
\makeatletter
\newskip\UD@savsk
\newcommand*\UD@bsphack{%
\relax
\ifhmode\UD@savsk\lastskip\@savsk\lastskip\@savsf\spacefactor\fi
}%
\newcommand*\UD@esphack{%
\relax
\ifhmode
\spacefactor\@savsf
\ifdim\@savsk>\z@
\ifdim\lastskip=\z@\nobreak\hskip\z@skip\fi
% The following \hskips are used for restoring \lastskip.
% I hope there are no evil side-effects. ;-)
\nobreak\hskip-\UD@savsk
\nobreak\hskip\UD@savsk
\ignorespaces
\fi
\fi
}%
%
%
\zref@newprop{labelname}{}%
\DeclareRobustCommand\LabelWhoseNameCanBeShown[1]{%
\UD@bsphack
\zref@setcurrent{labelname}{#1}%
\zref@labelbyprops{#1}{labelname}%
\label{#1}%
\UD@esphack
}%
\DeclareRobustCommand\ReferNameOfLabelWhoseNameCanBeShown[1]{%
\zref@extractdefault{#1}%
{labelname}%
{\nfss@text{\reset@font\bfseries ??}\refused{#1}}%
}%
\makeatother
\pagestyle{empty}
\textwidth=\paperwidth
\addtolength\textwidth{-4cm}%
\oddsidemargin=2cm
\addtolength\oddsidemargin{-1in}%
\addtolength\oddsidemargin{-\hoffset}%
\evensidemargin=\oddsidemargin
\marginparwidth=1.5cm
\marginparsep=0.25cm
\parindent=0ex
\parskip=\medskipamount
\begin{document}
Referencing the thing:
\sloppy
\verb|\ReferNameOfLabelWhoseNameCanBeShown{A unique label name}|:
\mbox{\ReferNameOfLabelWhoseNameCanBeShown{A unique label name}}
\verb|\ref{A unique label name}|:
\mbox{\ref{A unique label name}}
\verb|\pageref{A unique label name}|:
\mbox{\pageref{A unique label name}}
\verb|\nameref{A unique label name}|:
\mbox{\nameref{A unique label name}}
\verb|\hyperref[{A unique label name}]{\ReferNameOfLabelWhoseNameCanBeShown{A unique label name}}|:
\mbox{\hyperref[{A unique label name}]{\ReferNameOfLabelWhoseNameCanBeShown{A unique label name}}}
\null\hrulefill\null
\begin{verbatim}
\section{A section}
\section{Another section}
% Introducing the thing:
\LabelWhoseNameCanBeShown{A unique label name}%
% If you wish to see the thing immediately, just reference it immediately:
\ReferNameOfLabelWhoseNameCanBeShown{A unique label name}
Some text. Some text. Some text. Some text. Some text. Some text.
Some text. Some text. Some text. Some text. Some text. Some text.
Some text. Some text. Some text. Some text. Some text. Some text.
\end{verbatim}
\section{A section}
\section{Another section}
% Introducing the thing:
\LabelWhoseNameCanBeShown{A unique label name}%
% If you wish to see the thing immediately, just reference it immediately:
\ReferNameOfLabelWhoseNameCanBeShown{A unique label name}
Some text. Some text. Some text. Some text. Some text. Some text.
Some text. Some text. Some text. Some text. Some text. Some text.
Some text. Some text. Some text. Some text. Some text. Some text.
\end{document}
或者,您可以创建宏,然后
\IDpar{⟨Unique ID⟩}
\ReferIDpar{⟨Unique ID⟩}
\HyperReferIDpar{⟨Unique ID⟩}
\IDpar
创建一个新段落并将其 ID 写入边注中。\ReferIDpar
让您引用该 ID,如果未通过引入该 ID,则会生成错误消息\IDpar
。\HyperReferIDpar
另外将引用转换为可点击的超链接,以便导航至所引用的段落。
您仍然需要手动提供 ID,因此您可能希望在 TeX 源文件中将已使用的 ID 列表作为注释保留下来:
\documentclass[parskip=full, mpinclude=true, twoside=semi]{scrbook}
\usepackage{marginnote}
\usepackage{xcolor}
\usepackage{hyperref}
% Number \subparagraph
\setcounter{secnumdepth}{5}
% Add \subparagraph to TOC (not important for the MWE)
\setcounter{tocdepth}{5}
% Color \subparagraph
% \addtokomafont{subparagraph}{\color{red}}
%
\makeatletter
\DeclareRobustCommand\FormatIDOfPar[1]{%
\hbox to 2cm{\null\hfill\textnormal{#1}\hbox to 5mm{}}%
}%
\newcommand\IDlabelPrefix{SPEC.}%
\newcommand\IDPrefix{SPEC\protect~}%
\DeclareRobustCommand\IDpar[1]{%
\par\leavevmode
\marginpar{%
\FormatIDOfPar{%
\begingroup
\@ifundefined{Hy@raisedlink}{}{%
\Hy@raisedlink{\hyper@anchorstart{\IDlabelPrefix#1}\hyper@anchorend}%
}%
\ReferIDpar{#1}%
\def\@currentlabel{\IDPrefix#1}%
\def\@currentHref{\IDlabelPrefix#1}%
\label{\IDlabelPrefix#1}%
\endgroup
}%
}%
\ignorespaces
}%
\@ifpackageloaded{hyperref}{%
\DeclareRobustCommand\ReferIDpar[1]{%
\ref*{\IDlabelPrefix#1}%
}%
\DeclareRobustCommand\HyperReferIDpar[1]{%
\hyperref[\IDlabelPrefix#1]{\ref*{\IDlabelPrefix#1}}%
}%
}{%
\DeclareRobustCommand\ReferIDpar[1]{%
\ref{\IDlabelPrefix#1}%
}%
\DeclareRobustCommand\HyperReferIDpar[1]{%
\ref{\IDlabelPrefix#1}%
}%
}%
\makeatother
\reversemarginpar
% List of IDs used so far:
% ========================
% (As in this example IDs are continuously numbered and I increased the
% number whenever introducing another ID, it is sufficient to keep
% track of the number of the ID that was introduced as the last one.)
%
% Last ID introduced: 12
% Date of introduction: Feb 11, 2019; 22:08:34 (UTC)
%
% Otherwise you could maintain a list of IDs for looking up whether
% an ID you intend to introduce already exists:
%
% \IDpar | currently in capter/section
% -----------------------------------------
% 1 | Nice chapter
% 2 | Nice section
% 3 | Nice subsection
% 4 | Nice subsubsection
% 5 | Nice paragraph
% 5a | - existed in some previous relase(s) of the document/meanwhile removed. -
% 6 | Nice subparagraph
% 7 | Nice subparagraph
% 8 | Nice other section
% 9 | Nice other subsection
% 10 | Nice other subsubsection
% 11 | Nice other paragraph
% 12 | Nice other subparagraph
%
% (I suggest keeping track of removed IDs also for ensuring that with
% later versions of the document, where probably specifications got
% removed, you don't erroneously -eh- "recycle" old removed
% specification-IDs ...)
\begin{document}
%\tableofcontents
\chapter{Nice chapter}
\IDpar{1} Test text. Test text. Test text.
\section{Nice section}
\IDpar{2} Test text. Test text. Test text.
\subsection{Nice subsection}
\IDpar{3} Test text. Test text. Test text.
\subsubsection{Nice subsubsection}
\IDpar{4} Test text. Test text. Test text.
\paragraph{Nice paragraph}
\IDpar{5} Test text. Test text. Test text.
\subparagraph{Nice subparagraph}
\IDpar{6} Test text. Test text. Test text.\\
\verb|\ReferIDpar{7}|: \ReferIDpar{7}\\
\verb|\HyperReferIDpar{7}|: \HyperReferIDpar{7}\\
\verb|\ReferIDpar{8}|: \ReferIDpar{8}\\
\verb|\HyperReferIDpar{8}|: \HyperReferIDpar{8}\\
\verb|\ReferIDpar{9}|: \ReferIDpar{9}\\
\verb|\HyperReferIDpar{9}|: \HyperReferIDpar{9}\\
\verb|\ReferIDpar{10}|: \ReferIDpar{10}\\
\verb|\HyperReferIDpar{10}|: \HyperReferIDpar{10}\\
\verb|\ReferIDpar{11}|: \ReferIDpar{11}\\
\verb|\HyperReferIDpar{11}|: \HyperReferIDpar{11}\\
\verb|\ReferIDpar{12}|: \ReferIDpar{12}\\
\verb|\HyperReferIDpar{12}|: \HyperReferIDpar{12}\\
\IDpar{7} Test text. Test text. Test text.
\section{Nice other Section}
\IDpar{8} Test text. Test text. Test text.
\subsection{Nice other subsection}
\IDpar{9} Test text. Test text. Test text.
\subsubsection{Nice other subsubsection}
\IDpar{10} Test text. Test text. Test text.
\paragraph{Nice other paragraph}
\IDpar{11} Test text. Test text. Test text.
\subparagraph{Nice other subparagraph}
\IDpar{12} Test text. Test text. Test text.
\verb|\ReferIDpar{1}|: \ReferIDpar{1}\\
\verb|\HyperReferIDpar{1}|: \HyperReferIDpar{1}\\
\verb|\ReferIDpar{2}|: \ReferIDpar{2}\\
\verb|\HyperReferIDpar{2}|: \HyperReferIDpar{2}\\
\verb|\ReferIDpar{3}|: \ReferIDpar{3}\\
\verb|\HyperReferIDpar{3}|: \HyperReferIDpar{3}\\
\verb|\ReferIDpar{4}|: \ReferIDpar{4}\\
\verb|\HyperReferIDpar{4}|: \HyperReferIDpar{4}\\
\verb|\ReferIDpar{5}|: \ReferIDpar{5}\\
\verb|\HyperReferIDpar{5}|: \HyperReferIDpar{5}\\
\verb|\ReferIDpar{6}|: \ReferIDpar{6}\\
\verb|\HyperReferIDpar{6}|: \HyperReferIDpar{6}\\
\end{document}