有没有办法检查 LaTeX 中是否已经定义了标签?

Jor*_*rdi 4 label latex

我在 David Hanak 的回答之后编辑了这个问题(顺便说一句,谢谢!)。他帮助了语法,但似乎我没有使用正确的函数开始。

基本上我想要的是让编译器忽略某个标签的多个定义而只使用第一个。为了做到这一点,我想我会做这样的事情:

    \makeatletter
    \newcommand{\mylabel}[1]{
        \@ifundefined{#1}{\label{#1}}{X}
    }
    \makeatother

但这不起作用,因为始终选择第一个选项(是否定义标签无关紧要)。我认为 \@ifundefined (和建议的 \ifundefined)仅适用于命令而不适用于标签,但我对 LaTeX 了解不多。对此的任何帮助都会很棒!谢谢!

很久以后的更新:我将 David Hanak 的回答标记为对我的问题的正确答案,但这不是一个完整的解决方案,尽管它确实帮助了我。问题是,我认为但我不是专家,即使 David 的代码检查是否定义了标签,它也仅在上次运行中定义了标签(即在 .aux 文件中)时才有效。如果在同一次运行中定义了两个同名的 \mylabels,则仍将定义第二个。此外,即使您设法解决此问题,它也会使 LaTeX 使用您按时间顺序定义的第一个标签,而不一定是文本中的第一个标签。无论如何,下面是我快速而肮脏的解决方案。它使用了计数器似乎立即被定义的事实。

\newcommand{\mylabel}[1]{%
    \@ifundefined{c@#1}{%
        \newcounter{#1}%
        \setcounter{#1}{0}%
    {}%
    \ifthenelse{\value{#1} > 0}{}{%
        \标签{#1}%
        \addtocounter{#1}{1}%
    }%
}

我不确定是否有必要将计数器初始化为 0,因为这似乎是一个可能的默认值,但我找不到是否是这种情况,所以我只是为了安全。此外,这使用了 'ifthen' 包,我不确定这是否必要。

Dav*_*nak 6

@是LaTeX 中的一个特殊字符。为了使您的声明在语法上正确,您必须再添加两行:

\makeatletter
\newcommand{\mylabel}[1]{
    \@ifundefined{#1}{\label{#1}}{X}
}
\makeatother
Run Code Online (Sandbox Code Playgroud)

第一行变成@普通字母,最后一行反转其效果。

更新:您可能还想看看“普通” \ifundefinedLaTeX 宏

更新2

好吧,我做了一些研究来找出真正问题的答案。问题是,定义标签并不会创建具有该名称的宏;而是创建宏。它在前面添加了一个“r@”。所以请尝试以下操作:

\makeatletter
\newcommand{\mylabel}[1]{
    \@ifundefined{r@#1}{\label{#1}}{X}
}
\makeatother
Run Code Online (Sandbox Code Playgroud)

有关更多技术细节,请参阅 LaTeX 发行版中 Latex.ltx 的第 3863 行(其中显示\def\newlabel{\@newl@bel r})。

  • 我认为如果您通过此宏创建标签并多次调用此宏(例如 \mylabel{test} \mylabel{test} 将不起作用),则这不起作用。我认为 (pdf)Latex 检查上次运行的临时文件中的 ifundefined :因此,如果您第一次运行此命令,ifundefine 始终为 false,第二次它始终为 true,第三次再次运行为 false,依此类推。 (2认同)

小智 6

我也不是 LaTeX 专家,但是经过一天的尝试和搜索互联网后,以下内容对我有用。我使用了一个虚拟计数器来解决这个问题。希望这会有所帮助,显然没有多少人在寻找这个。

\newcommand{\mylabel}[1]{
    \ifcsname c@#1\endcsname%
    \else%
        \newcounter{#1}\label{#1}%
    \fi%
}
Run Code Online (Sandbox Code Playgroud)