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

发布于 2024-07-12 19:46:29 字数 1020 浏览 3 评论 0原文

我在大卫·哈纳克(David Hanak)回答后编辑了问题(谢谢顺便说一句!)。 他帮助解决了语法问题,但看来我一开始就没有使用正确的函数。

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

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

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

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

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

我不确定是否有必要将计数器初始化为 0,因为这似乎是默认值,但我找不到是否是这种情况,所以我只是为了安全起见。 另外,这使用了“ifthen”包,我不确定是否有必要。

I edited the question after David Hanak's answer (thanks btw!). He helped with the syntax, but it appears that I wasn't using the right function to begin with.

Basically what I want is to let the compiler ignore multiple definitions of a certain label and just use the first. In order to do that, I thought I'd just do something like this:

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

This does not work though, because the first option is always chosen (it doesn't matter if the label is defined or not). I think the \@ifundefined (and the suggested \ifundefined) only work for commands and not for labels, but I don't really know much about LaTeX. Any help with this would be great! Thanks!

Much later update:
I marked David Hanak's response as the correct answer to my question, but it isn't a complete solution, although it really helped me.
The problem is, I think but I'm no specialist, that even though David's code checks to see if a label is defined, it only works when the label was defined in a previous run (i.e. is in the .aux file). If two \mylabels with the same name are defined in the same run, the second will still be defined. Also, even if you manage to work around this, it will make LaTeX use the first label that you defined chronologically, and not necessarily the first in the text.
Anyway, below is my quick and dirty solution. It uses the fact that counters do seem to be defined right away.

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

I'm not sure if it is necessary to initialize the counter to 0, as it seems like a likely default, but I couldn't find if that was the case, so I'm just being safe.
Also, this uses the 'ifthen' package, which I'm not sure is necessary.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

八巷 2024-07-19 19:46:29

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

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

第一行将 @ 转换为普通字母,最后一行反转其效果。

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

更新 2

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

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

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

@ is a special character in LaTeX. To make your declaration syntactically correct, you'll have to add two more lines:

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

The first line turns @ into a normal letter, the last line reverses its effect.

Update: You might also want to take a look at the "plain" \ifundefined LaTeX macro.

Update 2

Okay, I did some research to figure out the answer to the real problem. The thing is that defining a label does not create a macro by that name; it prepends a "r@" to it. So try the following:

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

For more technical details, refer to line 3863 of latex.ltx in your LaTeX distribution (where it says \def\newlabel{\@newl@bel r}).

-残月青衣踏尘吟 2024-07-19 19:46:29

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

\newcommand{\mylabel}[1]{
    \ifcsname c@#1\endcsname%
    \else%
        \newcounter{#1}\label{#1}%
    \fi%
}

I am also not a LaTeX expert, however after one day of trying and searching the internet the following worked for me. I have used a dummy counter to solve the problem. Hopefully this helps, apparently not many people are looking for this.

\newcommand{\mylabel}[1]{
    \ifcsname c@#1\endcsname%
    \else%
        \newcounter{#1}\label{#1}%
    \fi%
}
千纸鹤 2024-07-19 19:46:29

作者:Victor Eijkhout,“TeX by Topic”,第 143 页:

\def\ifUnDefinedCs#1{\expandafter\ifx\csname#1\endcsname\relax} 

这可用于检查标签是否已定义; 如果没有,则打印标签:

\newcommand{\myautoref}[1]{\ifUnDefinedCs{r@#1}{\color{magenta}\IDontKnow\{#1\}}\else\autoref{#1}\fi} 

By Victor Eijkhout, "TeX by Topic", p.143:

\def\ifUnDefinedCs#1{\expandafter\ifx\csname#1\endcsname\relax} 

This can be used to check whether a label is defined; if not, the label is printed:

\newcommand{\myautoref}[1]{\ifUnDefinedCs{r@#1}{\color{magenta}\IDontKnow\{#1\}}\else\autoref{#1}\fi} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文