用于格式化任意数量方程的命令

用于格式化任意数量方程的命令

我在这里读到了很多关于新命令中逗号分隔参数列表的条目。我无法让它们适应我的需求,所以我在这里提出了我的问题。

我想要这样的命令:

\eqsRef{equ:name_one, equ:name_two, equ:name_three} % with any number of arguments

其中 'equ:foo_bar' 是方程标签,始终包含冒号并且经常带有下划线字符,其产生与此等同的内容:

Eqs.~(\ref{equ:name_one}, \ref{equ:name_two}, \ref{equ:name_three})

但可以带有任意数量的参数。也就是说,它会打印例如

等式(3、45、62)

如果提供的方程标签恰好是那些方程编号。

奖励(不是真正需要的但是...):如果只提供了一个参数,那么写“Eq.~”而不是“Eqs.~”。

我很乐意接受使用或不使用额外包的解决方案。

答案1

以下示例定义了\eqsRef获取 s 列表<label>并使用以下方法处理该列表etoolbox's \docsvlist。通过计算使用的 s 的数量来实现复数化<label>

在此处输入图片描述

\documentclass{article}

\usepackage{etoolbox,amsmath}

\newcounter{eqncount}

% \eqsRef{<csv of labels to equations>}
\newcommand{\eqsRef}[1]{%
  \setcounter{eqncount}{0}% Restart equation counter
  \renewcommand*{\do}[1]{\stepcounter{eqncount}}% Step equation reference counter
  \docsvlist{#1}% Count number of equation references
  Eq%
  \ifnum\value{eqncount}>1
    s% Plural
  \fi
  .\nobreakspace
  % https://tex.stackexchange.com/a/89187/5764
  \def\eqnrefdelim{\def\eqnrefdelim{, }}%
  \renewcommand{\do}{\eqnrefdelim\ref}%
  \textup{(}%
    \docsvlist{#1}%
  \textup{)}%
}

\begin{document}

\begin{align}
  f(x) \label{eqn:first} \\
  s(x) \label{eqn:second} \\
  t(x) \label{eqn:third} \\
  l(x) \label{eqn:last}
\end{align}

\eqsRef{eqn:first, eqn:second, eqn:last}

\eqsRef{eqn:third}

\end{document}

引用位于\textup{(}...\textup{)}系列内,这意味着括号始终是直立的。还可根据需要引入其他格式注意事项。

答案2

输入以逗号分隔,然后以每个项目作为参数来创建一个新序列\ref

最后打印列表;如果只有一个项目,则其前面是 ,Eq.否则列表前面是Eqs.

项周围的前导或尾随空格将被忽略。因此

\eqrefs{equ:name_one, equ:name_two, equ:name_three}
\eqrefs{equ:name_one,equ:name_two,equ:name_three}
\eqrefs{ equ:name_one , equ:name_two, equ:name_three }

是等效的。

\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\eqrefs}{m}
 {% #1 = list of labels
  \joansola_eqrefs:n { #1 }
 }

\seq_new:N \l__joansola_eqrefs_in_seq
\seq_new:N \l__joansola_eqrefs_out_seq

\cs_new_protected:Nn \joansola_eqrefs:n
 {
  \seq_set_split:Nnn \l__joansola_eqrefs_in_seq { , } { #1 }
  \seq_set_map:NNn \l__joansola_eqrefs_out_seq \l__joansola_eqrefs_in_seq
   {
    \exp_not:n { \ref{##1} }
   }
  \int_compare:nTF { \seq_count:N \l__joansola_eqrefs_out_seq < 2 }
   { Eq.\nobreakspace }
   { Eqs.\nobreakspace }
  \textup{(\seq_use:Nn \l__joansola_eqrefs_out_seq {,~})}
 }
\ExplSyntaxOff

\begin{document}

\begin{align}
a&=b \label{equ:name_one} \\
c&=d \label{equ:name_two} \\
e&=f \label{equ:name_three}
\end{align}

\eqrefs{equ:name_one, equ:name_two, equ:name_three}

\eqrefs{equ:name_one, equ:name_three}

\eqrefs{equ:name_one}

\end{document}

在此处输入图片描述

答案3

使用包的方法xinttools,部分xint图书馆。

\documentclass{article}

\usepackage{amsmath}

\usepackage{xinttools}

% \eqsRef{<csv of labels to equations>}
\newcommand{\eqsRef}[1]{%
  % First we trim from the input items leading and trailing spaces
  % The argument #1 is allowed to be a macro, say, \mylist, holding
  % the values, because \xintCSVtoList applies expansion to it 
  % (this means the first item will also be submitted to some expansion)
  \oodef\eqsRefinput{\xintCSVtoList{#1}}%
  % count how many items and typeset either Eq. or Eqs.
  Eq\ifnum\xintNthElt{0}{\eqsRefinput}>1
    s% Plural
  \fi
  .\nobreakspace
  \textup{(}%
  % Do now an \xintFor* loop to act upon each item
  \xintFor* ##1 in \eqsRefinput:
  {\xintifForFirst{}{\xintifForLast{ and }{, }}\ref{##1}}%
  \textup{)}%
}%

\begin{document}

\begin{align}
  f(x) \label{eqn:first} \\
  s(x) \label{eqn:second} \\
  t(x) \label{eqn:third} \\
  u(x) \label{eqn:fourth} \\
  l(x) \label{eqn:last}
\end{align}

\eqsRef{eqn:first, eqn:third, eqn:last}

\eqsRef{eqn:third}

\end{document}

在此处输入图片描述

答案4

您希望使用逗号列表解析。

是啊!(La)TeX 中的逗号列表解析很有趣,因为

  • 您需要注意单个物品周围的空间。

  • 您需要注意用一对括号括住整个单个项目,以便屏蔽标签名称中的逗号和空格。还请注意,您只需执行\label{} ... 即可获得“无名”引用标签\ref{}

  • 它总是提供重新发明轮子的机会。;-)

我接受了可扩展地完成所有事情的挑战(即,没有任何循环等定义临时宏),没有禁用标记,没有\if…-switches,没有像 eTeX 这样的扩展,没有额外的包。

我不提供任何保证。

如果您认为需要编辑此帖子来纠正与拼写无关/与英语无关但与代码相关的错误/错误,请给我提示。;-)

(好吧,如果您认为需要编辑这篇文章来纠正与拼写/英语相关的错误,当然,您也可以给我提示。;-))

\documentclass{article}

\makeatletter
%%//////////////////////////////////////////////////////////////////////////////
%% SECTION LICENCE AND COPYRIGHT
%%
%% Copyright (C) 2018 by  Ulrich W. Diez ([email protected])
%%..............................................................................
%% This work may be distributed and/or modified under the conditions of the
%% LaTeX Project Public Licence (LPPL), either version 1.3 of this license or 
%% (at your option) any later version. 
%% (The latest version of this license is in:
%%    http://www.latex-project.org/lppl.txt
%%  and version 1.3 or later is part of all distributions of 
%%  LaTeX version 1999/12/01 or later.)
%% The author of this work is Ulrich Diez.
%% This work has the LPPL maintenance status ‘not maintained’.
%% Usage of any/every component of this work is at your own risk.
%% There is no warranty — neither for probably included documentation nor for 
%% any other part/component of this work.
%% If something breaks, you usually may keep the pieces.
%%
%% EOF SECTION LICENCE AND COPYRIGHT
%%//////////////////////////////////////////////////////////////////////////////
%%
%%
%%//////////////////////////////////////////////////////////////////////////////
%% SECTION PARAPHERNALIA:
%% 
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@Exchange, \UD@CheckWhetherNull, 
%%    \UD@CheckWhetherBlank
%%==============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@Exchange[2]{#2#1}%
%%------------------------------------------------------------------------------
%% Check whether argument is empty:
%%..............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%------------------------------------------------------------------------------
%% Check whether argument is blank (empty or only spaces):
%%..............................................................................
%% -- Take advantage of the fact that TeX discards space tokens when
%%    "fetching" _un_delimited arguments: --
%% \UD@CheckWhetherBlank{<Argument which is to be checked>}%
%%                      {<Tokens to be delivered in case that
%%                        argument which is to be checked is blank>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked is not blank}%
\newcommand\UD@CheckWhetherBlank[1]{%
  \romannumeral\expandafter\expandafter\expandafter\UD@secondoftwo
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo#1{}.}%
}%
%%
%% EOF SECTION PARAPHERNALIA
%%//////////////////////////////////////////////////////////////////////////////
%%
%%
%%//////////////////////////////////////////////////////////////////////////////
%% SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
%%
%%  - REQUIRES SECTION PARAPHERNALIA.
%% 
%%   The obscure case of removing several leading/trailing spaces was taken 
%%   into consideration.
%%
%%   Removal of spaces was implemented in a way where no brace-stripping from
%%   the arguments takes place. 
%%   Explicit-catcode-1/2-character-token-pairs remain untouched.
%%
%%   Spaces interspersing the argument or hidden within braces will be left in
%%   place.
%%
%%   The arguments themselves do not get expanded.
%%
%%   (For some obscure reason I don't remember any more I needed this in the
%%    past.)
%%
%%==============================================================================
%% Check whether brace-balanced argument starts with a space-token
%%..............................................................................
%% \UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
%%                             {<Tokens to be delivered in case <argument
%%                               which is to be checked>'s 1st token is a
%%                               space-token>}%
%%                             {<Tokens to be delivered in case <argument
%%                               which is to be checked>'s 1st token is not
%%                               a space-token>}%
\newcommand\UD@CheckWhetherLeadingSpace[1]{%
  \romannumeral0\UD@CheckWhetherNull{#1}%
  {\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}%
  {\expandafter\UD@secondoftwo\string{\UD@CheckWhetherLeadingSpaceB.#1 }{}}%
}%
\newcommand\UD@CheckWhetherLeadingSpaceB{}%
\long\def\UD@CheckWhetherLeadingSpaceB#1 {%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@secondoftwo#1{}}%
  {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
  {\UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter
   \expandafter\expandafter\expandafter}\expandafter\expandafter
   \expandafter}\expandafter\UD@secondoftwo\expandafter{\string}%
}%
%%==============================================================================
%% \UD@TrimAllLeadSpace{<action>}{<argument>} 
%%..............................................................................
%%   expandably removes all leading spaces from  <argument> in case at least
%%   one leading space is present. 
%%   Then
%%     <action>{<argument without leading spaces>}
%%   is performed.
%%==============================================================================
\newcommand\UD@TrimAllLeadSpace[2]{%
  \romannumeral0\UD@TrimAllLeadSpaceLoop{#2}{#1}%
}%
\newcommand\UD@TrimAllLeadSpaceLoop[2]{%
  \UD@CheckWhetherLeadingSpace{#1}%
                            {%
                              \expandafter\UD@TrimAllLeadSpaceLoop
                              \expandafter{\UD@removespace#1}{#2}%
                            }%
                            { #2{#1}}%
}%
\newcommand\UD@removespace{}\UD@firstoftwo{\def\UD@removespace}{} {}%
%%==============================================================================
%% \UD@TrimAllTrailSpace{<action>}{<argument>} 
%%..............................................................................
%%   expandably removes all trailing spaces from  <argument> in case at least
%%   one trailing space is present. 
%%   Then
%%     <action>{<argument without trailing spaces>}
%%   is performed.
%%==============================================================================
\newcommand\UD@TrimAllTrailSpace[2]{%
   \romannumeral0\UD@TrimTrailSpaceLoop{#2}{#1}%
}%
%%------------------------------------------------------------------------------
%% \UD@TrimTrailSpaceLoop{<list of space-delimited arguments>}{<action>}
%%..............................................................................
%%   both extracts the first space-delimited argument from the <list of space-
%%   delimited arguments> as {<current argument with one trailing space 
%%   removed>} and removes it from the <list of space-delimited arguments> for
%%   obtaining the <remaining list of space delimited arguments> and passes 
%%   these two things and an empty list of <arguments preceding the current
%%   argument gathered so far> and the <action> to perform at the end of the 
%%   iteration to \UD@CheckWhetherLastSpaceDelimitedItem.
%%
%%   \UD@CheckWhetherLastSpaceDelimitedItem in turn does choose the next
%%   action.
\newcommand\UD@TrimTrailSpaceLoop[2]{%
  \UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1 \UD@SeLDom}{%
    \expandafter\UD@CheckWhetherLastSpaceDelimitedItem
    \expandafter{\UD@RemoveTokensTillNextSpace.#1 }%
  }{}{#2}%
}%
%%------------------------------------------------------------------------------
%% Macros for \UD@ObtainFirstSpaceDelimitedTokenSetLoop.
%%
\newcommand*\UD@RemoveTokensTillNextSpace{}%
  \long\def\UD@RemoveTokensTillNextSpace#1 {}%
\newcommand*\UD@BraceStripRemoveNextSpace{}%
  \long\def\UD@BraceStripRemoveNextSpace#1 {#1}%
\newcommand*\UD@GetFirstSpaceDelimitedTokenSet{}%
  \long\def\UD@GetFirstSpaceDelimitedTokenSet#1 #2\UD@SeLDom{#1 }%
\newcommand\UD@gobbledot{}%
  \def\UD@gobbledot.{}%
%%------------------------------------------------------------------------------
%% \UD@ObtainFirstSpaceDelimitedTokenSetLoop%
%%     {<list of space delimited arguments>}%
%%     {<action>}%
%%
%% -> <action>{<first element of list of space delimited arguments>}%
%%...............................................................................
%% \UD@ObtainFirstSpaceDelimitedTokenSetLoop does--without unwanted brace-re-
%% moval--append the first space delimited argument from a
%% <list of space delimited arguments> as brace-delimited argument behind
%% a set of tokens given as <action>.
\newcommand\UD@ObtainFirstSpaceDelimitedTokenSetLoop[1]{%
  \expandafter\UD@CheckWhetherNull
  \expandafter{\UD@RemoveTokensTillNextSpace#1}{%
    \expandafter\expandafter\expandafter\UD@Exchange
    \expandafter\expandafter\expandafter{%
    \expandafter\expandafter\expandafter{%
    \expandafter\UD@gobbledot\UD@BraceStripRemoveNextSpace#1}}%
  }{%
    \expandafter\UD@ObtainFirstSpaceDelimitedTokenSetLoop
    \expandafter{\UD@GetFirstSpaceDelimitedTokenSet#1}%
  }%
}%
%%------------------------------------------------------------------------------
%% \UD@CheckWhetherLastSpaceDelimitedItem
%%    {<remaining list of space delimited arguments>}%
%%    {<current argument with one trailing space removed>}%
%%    {<arguments preceding the current argument gathered
%%      so far>}%
%%    {<action>}%
%%..............................................................................
%% Case 1: <remaining list of space delimited arguments> is
%%         empty.
%%         We are done: Thus:
%%         <space>% for terminating \romannumeral-expansion, and
%%         <action>{<arguments preceding the current argument gathered so
%%                   far><current argument with one trailing space removed>}
%% Case 2: <remaining list of space delimited arguments> consists of a single 
%%         space.
%%         A trailing space was removed. There may be more. Thus:
%%         \UD@TrimTrailSpaceLoop{%
%%           <arguments preceding the current argument gathered so
%%           far><current argument with one trailing space removed>%
%%         }{<action>}%
%% Neither case 1 nor case 2: 
%%         The <current argument with one trailing space  removed> is not the
%%         last argument of the list, thus:
%%         For the next iteration 
%%         - attach it and a trailing space to the <arguments preceding the
%%           current argument gathered so far>,
%%         - get the first space delimited argument of the <remaining list of 
%%           space delimited arguments> as  <current argument with one trailing
%%           space removed>
%%         - remove that first space delimited argument from the <remaining list 
%%           of space delimited arguments>
\newcommand\UD@CheckWhetherLastSpaceDelimitedItem[4]{%
  \UD@CheckWhetherNull{#1}{ #4{#3#2}}{%
    \UD@CheckWhetherLeadingSpace{#1}{%
      \expandafter\UD@CheckWhetherNull
      \expandafter{\UD@removespace#1}{\UD@firstoftwo}{\UD@secondoftwo}%
    }{\UD@secondoftwo}%
    {\UD@TrimTrailSpaceLoop{#3#2}{#4}}%
    {%
      \UD@ObtainFirstSpaceDelimitedTokenSetLoop{.#1\UD@SeLDom}{%
        \expandafter\UD@CheckWhetherLastSpaceDelimitedItem
        \expandafter{\UD@RemoveTokensTillNextSpace.#1}%
      }{#3#2 }{#4}%
    }%
  }%
}%
%%==============================================================================
%% \UD@TrimAllSurroundSpace{<action>}{<argument>} 
%%..............................................................................
%%   expandably removes all leading and trailing spaces from  <argument> in
%%   case at least one leading space is present. 
%%   Then
%%     <action>{<argument without leading and trailing spaces>}
%%   is performed.
%%==============================================================================
\newcommand\UD@TrimAllSurroundSpace[2]{%
  \romannumeral\UD@TrimAllLeadSpace{\UD@TrimAllTrailSpace{0 #1}}{#2}%
}%
%%
%% EOF SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
%%//////////////////////////////////////////////////////////////////////////////
%%
%%
%%//////////////////////////////////////////////////////////////////////////////
%% SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
%%
%%  - REQUIRES SECTION PARAPHERNALIA.
%%  - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
%% 
%%-----------------------------------------------------------------------------
%% Extract first inner comma-delimited argument:
%%
%% \UD@ExtractFirstCommaArg{<action>}{<comma list>}
%%
%% yields:
%% 
%% <action>{<first item/first comma-delimited argument from comma
%%           list with surrounding spaces and one level of surroundinng
%%           braces removed if present>}
%%
%% <comma-list> is considered a sequence of comma-delimited arguments.
%%
%% The <first item/first comma-delimited argument from comma list> 
%% will be extracted. The remainder of the <comma list> will be discarded.
%%
%% Then space tokens surrounding the <first item/first comma-delimited
%% argument from comma list> will be removed.
%%
%% If removal of surrounding spaces yields emptiness, no tokens will be
%% delivered.
%%
%% If removal of surrounding spaces does not yield emptiness, 
%%   - one pair of braces surrounding the entire result of space-removal
%%     will be removed if present!!!!!
%%
%%   - Then the result thereof, no matter if empty or not, will be wrapped 
%%     in braces and passed on to <action>.
%%
%% This implies you can have <comma-delimited arguments> contain
%% emptiness or commas and spaces by nesting them into braces.
%%
%% Examples:
%%
%%   \UD@ExtractFirstCommaArg{<action>}{,A,B,C,D,E} yields no token at all
%%
%%   \UD@ExtractFirstCommaArg{<action>}{{},A,B,C,D,E} yields <action>{}
%%
%%   \UD@ExtractFirstCommaArg{<action>}{A,B,C,D,E} yields  <action>{A}
%%
%%   \UD@ExtractFirstCommaArg{<action>}{{AB},C,D,E} yields  <action>{AB}
%%
%%   \UD@ExtractFirstCommaArg{<action>}{  AB  ,C,D,E} yields  <action>{AB}
%%
%%   \UD@ExtractFirstCommaArg{<action>}{  {AB}  ,C,D,E} yields  <action>{AB}
%%
%%   \UD@ExtractFirstCommaArg{<action>}{ { A, B } ,C,D,E} yields  <action>{ A, B }
%%
%%   \UD@ExtractFirstCommaArg{<action>}{ { {AB} } ,C,D,E} yields  <action>{ {AB} }
%% 
%% Due to \romannumeral0-expansion, the result will be delivered after
%% two expansion-steps/after having \UD@ExtractFirstCommaArg "hit" via
%% two \expandafter(-chains).
%%.............................................................................
\newcommand\UD@gobbletocomma{}\long\def\UD@gobbletocomma#1,{}%
\newcommand\UD@removecomma{}\long\def\UD@removecomma#1,{#1}%
\newcommand\UD@removebracesNrmstop[2]{%
  \UD@CheckWhetherNull{#2}{%
    0 %
  }{%
    \expandafter\UD@Exchange
    \expandafter{%
      \expandafter{\UD@removecomma#2,}%
    }{0 #1}%
  }%
}%
\newcommand\UD@RemoveFromCommaTillUD@SelDOm{}%
\long\def\UD@RemoveFromCommaTillUD@SelDOm#1,#2\UD@SelDOm{#1,}%
\newcommand\UD@ExtractFirstCommaArg[2]{%
  \romannumeral%
  \UD@ExtractFirstCommaArgLoop{.#2,\UD@SelDOm}{#1}%
}%
\newcommand\UD@ExtractFirstCommaArgLoop[2]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletocomma#1}%
  {%
     \expandafter\expandafter\expandafter\UD@Exchange
     \expandafter\expandafter\expandafter{%
     \expandafter\expandafter\expandafter{%
     \expandafter\UD@gobbledot\UD@removecomma#1}}%
     {\UD@TrimAllSurroundSpace{%
       \UD@removebracesNrmstop{#2}%
     }}%
  }%
  {%
    \expandafter\UD@ExtractFirstCommaArgLoop
    \expandafter{\UD@RemoveFromCommaTillUD@SelDOm#1}{#2}%
  }%
}%
%%
%% EOF SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST. 
%%//////////////////////////////////////////////////////////////////////////////
%%
%%
%%//////////////////////////////////////////////////////////////////////////////
%% SECTION EXPANDABLE ITERATION ON LIST OF LABELS
%%
%%  - REQUIRES SECTION PARAPHERNALIA.
%%  - REQUIRES SECTION EXPANDABLE REMOVAL OF LEADING AND TRAILING SPACES.
%%  - REQUIRES SECTION EXPANDABLE EXTRACTION OF FIRST ITEM OF COMMA-LIST.
%% 
%% \eqsRef{<comma-list>}%
%%
%% If <comma-list> contains only commas and/or space tokens, or is empty: 
%%   yields nothing.
%%   !!! Be aware that there is no \@bsphack..\@esphack for this case.
%%   This implies that you will get two spaces in this case if 
%%   the call to \EQsref has both a leading and a trailing space,
%%   i.e., is, e.g., <space>\EQsref{, ,}<space>   !!!
%%
%% If <comma-list> contains one item: 
%%   yields: Eq~(\ref{<item of comma-list>})
%%
%% If <comma-list> contains k items; k > 1: 
%%   yields:
%%     Eq~(\ref{<item 1 of comma-list>}%
%%         , \ref{<item 2 of comma-list>}%
%%         [...]%
%%         , \ref{<item k of comma-list>})%
%%
%% Due to \romannumeral0-expansion, the result will be delivered after two
%% expansion-steps/after having \eqsRef "hit" via two \expandafter(-chains).
%%
\newcommand\eqsRef[1]{%
  \romannumeral\UD@eqsRefiterator{}{#1,}%
}%
%% \UD@eqsRefiterator: #1 -- \ref-calls constructed so far
%%                     #2 -- (remaining) comma-list of labels
%%
\newcommand\UD@eqsRefiterator[2]{%
  \UD@CheckWhetherNull{#2}{%
     \UD@CheckWhetherBlank{#1}{0 }{%
       \expandafter\UD@CheckWhetherNull
       \expandafter{\UD@gobbletocomma#1,}{0 Eq}{0 Eqs}.~(#1)%
     }%
  }{%
    \expandafter\UD@Exchange\expandafter{%
       \expandafter{\UD@gobbletocomma#2}%
    }{%
      \expandafter\UD@eqsRefiterator\expandafter{%
        \romannumeral0%
        \expandafter\expandafter\expandafter\UD@CheckWhetherNull
        \expandafter\expandafter\expandafter{%
          \UD@ExtractFirstCommaArg{\ref}{#2}%
        }{ #1}{%
          \expandafter\expandafter\expandafter\UD@Exchange
          \expandafter\expandafter\expandafter{%
            \UD@ExtractFirstCommaArg{\ref}{#2}%
          }{%
            \UD@CheckWhetherNull{#1}{ }{ #1, }%
          }%
        }%
      }%   
    }%
  }%
}%
%%
%% EOF SECTION EXPANDABLE ITERATION ON LIST OF LABELS
%%//////////////////////////////////////////////////////////////////////////////
\makeatother


\newcommand\TestGobbleToGT{}%
\long\def\TestGobbleToGT#1>{}%
\newcommand\Test[1]{%
  \expandafter\expandafter\expandafter\def
  \expandafter\expandafter\expandafter\test
  \expandafter\expandafter\expandafter{%
    #1%
  }%
  \texttt{\expandafter\TestGobbleToGT\meaning\test}%
  \par\noindent\hrulefill
}%

\begin{document}

\section*{testing \texttt{\string\UD@ExtractFirstCommaArg}}

\makeatletter

\noindent\verb|\UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}| yields:\\
\Test{\UD@ExtractFirstCommaArg{<Action>}{,A,B,C,D,E}}%

\noindent\verb|\UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}| yields:\\
\Test{\UD@ExtractFirstCommaArg{<Action>}{ {} ,A,B,C,D,E}}%

\noindent\verb|\UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}| yields:\\
\Test{\UD@ExtractFirstCommaArg{<Action>}{{},A,B,C,D,E}}%

\noindent\verb|\UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}| yields:\\
\Test{\UD@ExtractFirstCommaArg{<Action>}{A,B,C,D,E}}%

\noindent\verb|\UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}| yields:\\
\Test{\UD@ExtractFirstCommaArg{<Action>}{{AB},C,D,E}}%

\noindent\verb|\UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}| yields:\\
\Test{\UD@ExtractFirstCommaArg{<Action>}{ {AB} ,C,D,E}}%

\noindent\verb|\UD@ExtractFirstCommaArg{<Action>}{  AB  ,C,D,E}| yields:\\
\Test{\UD@ExtractFirstCommaArg{<Action>}{  AB  ,C,D,E}}%

\noindent\verb|\UD@ExtractFirstCommaArg{<Action>}{  {AB},C,D,E}| yields:\\
\Test{\UD@ExtractFirstCommaArg{<Action>}{  {AB},C,D,E}}%

\noindent\verb|\UD@ExtractFirstCommaArg{<Action>}{{AB}  ,C,D,E}| yields:\\
\Test{\UD@ExtractFirstCommaArg{<Action>}{{AB}  ,C,D,E}}%

\noindent\verb|\UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}| yields:\\
\Test{\UD@ExtractFirstCommaArg{<Action>}{ { A, B } ,C,D,E}}%

\noindent\verb|\UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}| yields:\\
\Test{\UD@ExtractFirstCommaArg{<Action>}{ { {AB} } ,C,D,E}}%

\makeatother

\newpage
\section*{testing \texttt{\string\eqsRef}}

\noindent\verb|\eqsRef{ A ,B, C,D ,,,E, F}| yields:\\
\Test{\eqsRef{ A ,B, C,D ,,,E, F}}%

\noindent
Be aware that it is possible to have one nameless referencing-label, \\
 i.e. \verb|\label{}| ..\verb|\ref{}|.\\
Here the last thing denotes the nameless label:\\
\verb|\eqsRef{ { A } ,B,C,{}}| yields:\\
\Test{\eqsRef{ { A } ,B,C,{}}}%

\noindent\verb|\eqsRef{ C}| yields:\\
\Test{\eqsRef{ C}}%

\noindent\verb|\eqsRef{ , }| yields:\\
\Test{\eqsRef{ , }}%

\noindent\verb|\eqsRef{  }| yields:\\
\Test{\eqsRef{  }}%

\noindent\verb|\eqsRef{}| yields:\\
\Test{\eqsRef{}}%

\end{document}

在此处输入图片描述 在此处输入图片描述

相关内容