eqnarray:下划线的重新定义与包含下划线的标签冲突!

eqnarray:下划线的重新定义与包含下划线的标签冲突!

我使用的罗马下标下划线重新定义(见示例)阻止我在eqnarray环境中定义标签。我该如何解决这个问题?(当我使用时不会出现此问题align,但我现在确实需要使用eqnarray)。谢谢,豪尔赫。

例子:

\documentclass[twocolumn]{article}
\usepackage{amsmath}

\catcode`_=\active
\newcommand{_}{\ifmmode\expandafter\sbrm\else\string_\fi}
\newcommand{\sbrm}[1]{\sb{\mathrm{#1}}}

\begin{document}

This compiles:
\begin{align}
    1 \neq 2
\label{my_label_1}
\end{align}

This doesn't:
\begin{eqnarray}
    1 \neq 2
\label{my_label_2}
\end{eqnarray}

\end{document}

编译错误:

! Missing \endcsname inserted.
<to be read again> 
                   \sb 
l.3 ...mathrm  {l}}abel\sb {\mathrm  {2}}}{{2}{1}}

答案1

您可能已经知道答案的第一部分。第一个之所以有效,是因为标签处于文本模式,因此__。另一方面,第二个处于数学模式,因此_\sbrm,然后事情就变得疯狂了。为了确保您可以\label在加载之前重新定义amsmath以使其与您对话:

\makeatletter
\def\label#1{%
  \ifmmode
    \typeout{^^JLabel in math mode for \@currenvir^^J}
  \else
    \typeout{^^JLabel in horizontal mode for \@currenvir^^J}
  \fi
  \@bsphack
  \protected@write\@auxout{}%
         {\string\newlabel{#1}{{\@currentlabel}{\thepage}}}%
  \@esphack}

控制台屏幕将显示:

Label in horizontal mode for align

Label in math mode for eqnarray

就在抛出错误之前。

这是因为实现方式不同。align来自amsmath,所以他们可能更喜欢在水平模式下制作标签,而eqnarray来自 LaTeX 内核。

重新定义eqnarray使\label文本模式看起来太多了。也许我们可以做点什么\label……

请注意,我只是正在做这个,不推荐!

旧解决方案:

我们可以让它将的转换 \catcode_其他的,这样我们就不会使用它的宏含义:

\def\label{%
  \begingroup
  \catcode`\_=12
  \l@bel}

然后我们定义一个内部函数\l@bel来标记参数并写入.aux

\def\l@bel#1{%
  \@bsphack
  \protected@write\@auxout{}%
         {\string\newlabel{#1}{{\@currentlabel}{\thepage}}}%
  \@esphack
  \endgroup}

请注意,这些更改必须在加载之前完成,amsmath因为它存储了当前的定义,\label并且您希望它记住所做的更改。

新解决方案:

实际上,更强大的方法是不要重新定义内部\label,而是仅用 catcode 更改所需的内容对其进行修补,因为某些包(hyperref,我正在看你)可能会删除你的定义。

使用etoolbox我们可以设计一个hyperref兼容的解决方案。我们将 的旧含义存储\label在 中\old@ltx@label,然后创建\label与之前相同的包装器,然后将 附加到\endgroup\old@ltx@label所有这些都在 之后\begin{document}(不是 \begin{document}):

\usepackage{etoolbox}
\AfterEndPreamble{%
  \let\old@ltx@label\label
  \def\label{%
    \begingroup
    \catcode`\_=12
    \old@ltx@label}%
  \apptocmd\old@ltx@label\endgroup{}{}
}

不过,我还没有用其他交叉引用包测试过这个解决方案。它可能会破坏一些东西。

可编译文档:

\documentclass[twocolumn]{article}

\makeatletter
\def\label{%
  \begingroup
  \catcode`\_=12
  \l@bel}
\def\l@bel#1{%
  \@bsphack
  \protected@write\@auxout{}%
         {\string\newlabel{#1}{{\@currentlabel}{\thepage}}}%
  \@esphack
  \endgroup}
\makeatother

\usepackage{amsmath}

\catcode`_=\active
\newcommand{_}{\ifmmode\expandafter\sbrm\else\string_\fi}
\newcommand{\sbrm}[1]{\sb{\mathrm{#1}}}

\begin{document}

This compiles:
\begin{align}
    1 \neq 2
\label{my_label_1}
\end{align}

This doesn't:
\begin{eqnarray}
    1 \neq 2
\label{my_label_2}
\end{eqnarray}

Now both equation~\eqref{my_label_1} and~\eqref{my_label_2} compile :)

\end{document}

答案2

我认为这只是出于学术兴趣,因为eqnarray永远不应该被使用。

您采取了错误的方法来解决问题:因为您希望下划线在文本中打印为其自身,所以最简单的方法就是使其具有数学活性。

\documentclass[twocolumn]{article}
\usepackage[T1]{fontenc}
\usepackage{amsmath}

\newcommand{\sbrm}[1]{\sb{\mathrm{#1}}}
\catcode`_=12
\begingroup\lccode`~=`_ \lowercase{\endgroup\let~}\sbrm
\AtBeginDocument{\mathcode`_="8000 }

\begin{document}

This_compiles:
\begin{align}
    1 \neq 2
\label{my_label_1}
\end{align}

This_compiles_too:
\begin{eqnarray}
    1 \neq 2
\label{my_label_2}
\end{eqnarray}

\end{document}

在此处输入图片描述

相关内容