根据字符条件新命令

根据字符条件新命令

我创建了一个基本命令,旨在简单地加粗和移动文本以节省时间:

\newcommand*\Cote[1]{\footnotesize\emph{\textbf{#1}}}

当我想要这个结果时,我仍然必须使用此命令\Cote{我的文本}。我想使这个自动化,因为我想要替换的文本总是具有相同的结构,也就是知道一个大写字母 D,旁边是数字:D3或者D89或者D1023

所以我想要一个新的命令,仅适用于数字跟在我的字母 D 后面的情况。 像这样 :

\newcommand*\D[1]{\footnotesize\emph{\textbf{#1}}}

但必须后面跟着数字。否则我的很多单词都会被替换,会很乱。

我尝试使用\ifnum0\newcommand 中的命令,但没有成功。在其他主题中尝试搜索时也失败了,例如有条件地替换字符序列有任何想法吗 ?

我使用 LuaLatex。在此先致以衷心的感谢!

答案1

这个 tokencycle 似乎可以完成工作。如您所见,输入流中的中间宏和组对结果没有不良影响。

\documentclass{article}
\usepackage{tokcycle,xcolor}
\Characterdirective{\ifx D#1\Cotetest{D}\else\addcytoks{#1}\fi}
\newcommand\Cotetest[1]{\tcpeek\z
  \ifx0\z\Cotetrue\else
  \ifx1\z\Cotetrue\else
  \ifx2\z\Cotetrue\else
  \ifx3\z\Cotetrue\else
  \ifx4\z\Cotetrue\else
  \ifx5\z\Cotetrue\else
  \ifx6\z\Cotetrue\else
  \ifx7\z\Cotetrue\else
  \ifx8\z\Cotetrue\else
  \ifx9\z\Cotetrue\else\addcytoks{#1}\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
\newcommand\Cotetrue{%
  \tcpop\z
  \expandafter\Cote\expandafter{\z}%
  \Cotetest{}}
\def\Cote#1{\addcytoks{\bgroup\footnotesize\emph{\textbf{#1}}\egroup}}
\begin{document}
\tokencyclexpress
D7C2
D93
\textcolor{red}{D123abc}
Dcf
D 
D\today
\endtokencyclexpress
\end{document}

在此处输入图片描述

补充

为了回应 OP 的评论,希望在改变的字体中保留“D”,如果出现后续数字,我可能会这样做:

\documentclass{article}
\usepackage{tokcycle,xcolor}
\Characterdirective{\ifx D#1\Cotetest{D}\else\addcytoks{#1}\fi}
\newcommand\Cotetest[1]{\tcpeek\z
  \ifx0\z\Cotetrue{#1}\else
  \ifx1\z\Cotetrue{#1}\else
  \ifx2\z\Cotetrue{#1}\else
  \ifx3\z\Cotetrue{#1}\else
  \ifx4\z\Cotetrue{#1}\else
  \ifx5\z\Cotetrue{#1}\else
  \ifx6\z\Cotetrue{#1}\else
  \ifx7\z\Cotetrue{#1}\else
  \ifx8\z\Cotetrue{#1}\else
  \ifx9\z\Cotetrue{#1}\else\addcytoks{#1}\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
\newcommand\Cotetrue[1]{%
  \tcpop\z
  \expandafter\Cote\expandafter{\expandafter#1\z}%
  \Cotetest{\empty}}
\def\Cote#1{\addcytoks{\bgroup\footnotesize\emph{\textbf{#1}}\egroup}}
\begin{document}
\tokencyclexpress
D7C2
D93
\textcolor{red}{D123abc}
Dcf
D 
D\today
\endtokencyclexpress
\end{document}

在此处输入图片描述

答案2

这是一个例行公事

\SurroundDDigits{⟨formatting command which takes one undelimited argument⟩}{⟨tokens⟩}

在尾递归循环中检查⟨代币⟩无需展开它们。尾递归/展开由\romannumeral直到检查完所有标记。当检查完所有标记后,TeX-⟨数字⟩-数量为 0 的值,后面跟着由结果形成的标记,结果是 TeX,因为遇到了⟨数字⟩-数量,停止收集⟨数字⟩为了\romannumeral聚集的⟨数字⟩-数量值为 0 时不会返回任何令牌,因为 0 不是正数。

模式序列+ 结果中属于 { , , , , , , , , }元素的非空标记序列 嵌套在花括号 (和
D11012112212312412512612712812912
{1}2) 之间,其中左花括号前面是⟨接受一个未限定参数的格式化命令⟩

作为结果的副作用

  • 类别代码 1(begin-group)的任何显式字符标记都被类别代码 1 的显式 { 替换,并且
  • 类别代码 2(结束组)的任何显式字符标记都被类别代码 2 的显式 } 替换。

由于\romannumeral-expansion,结果是通过触发两个扩展步骤/两次“命中”后得出的\expandafter

我尽力确保扩展不会在对齐/表格等内受到干扰,但不提供任何保证。

为了好玩,我没有使用任何 ε-TeX-、LuaTeX- 或 pdfTeX- 扩展或类似的东西,并且我避免使用任何\if...\else...\fi- 和任何\csname..\endcsname- 表达式。
因此,此类表达式的(不平衡部分)出现在⟨代币⟩不干扰扩张。

感叹号作为参数分隔符在一个地方被大量使用。
如果感叹号的大写代码或小写代码被更改,并且扩展操作的过程在应用\uppercase/ 的相应阶段被拦截,这可能会给你带来麻烦\lowercase。由于扩展一直持续\romannumeral到获得结果,这种情况极不可能发生,即使可能的话。

使用风险由您自行承担。

\errorcontextlines=10000
\makeatletter
%%=============================================================================
%% PARAPHERNALIA:
%% \UD@firstoftwo, \UD@secondoftwo, \UD@PassFirstToSecond, \UD@Exchange,
%% \UD@removespace, \UD@stopromannumeral, \UD@CheckWhetherNull,
%% \UD@CheckWhetherBrace, \UD@CheckWhetherLeadingExplicitSpace,
%% \UD@ExtractFirstArg
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
\@ifdefinable\UD@removespace{\UD@Exchange{ }{\def\UD@removespace}{}}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
%% 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]{%
  \romannumeral\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
  \expandafter\UD@stopromannumeral\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{}{}}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% \CheckWhetherBrace{<Argument which is to be checked>}%
%%                   {<Tokens to be delivered in case that argument
%%                     which is to be checked has a leading
%%                     explicit catcode-1-character-token>}%
%%                   {<Tokens to be delivered in case that argument
%%                     which is to be checked does not have a
%%                     leading explicit catcode-1-character-token>}%
\newcommand\UD@CheckWhetherBrace[1]{%
  \romannumeral\expandafter\UD@secondoftwo\expandafter{\expandafter{%
  \string#1.}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@firstoftwo}{%
  \expandafter\UD@stopromannumeral\UD@secondoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument starts with a space-token
%%.............................................................................
%% \UD@CheckWhetherLeadingExplicitSpace{<Argument which is to be checked>}%
%%                                     {<Tokens to be delivered in case <argument
%%                                       which is to be checked> does have a
%%                                       leading explicit space-token>}%
%%                                     {<Tokens to be delivered in case <argument
%%                                       which is to be checked> does not have a
%%                                       a leading explicit space-token>}%
\newcommand\UD@CheckWhetherLeadingExplicitSpace[1]{%
  \romannumeral\UD@CheckWhetherNull{#1}%
  {\expandafter\UD@stopromannumeral\UD@secondoftwo}%
  {%
    % Let's nest things into \UD@firstoftwo{...}{} to make sure they are nested in braces
    % and thus do not disturb when the test is carried out within \halign/\valign:
    \expandafter\UD@firstoftwo\expandafter{%
      \expandafter\expandafter\expandafter\UD@stopromannumeral
      \romannumeral\expandafter\UD@secondoftwo
      \string{\UD@CheckWhetherLeadingExplicitSpaceB.#1 }{}%
    }{}%
  }%
}%
\@ifdefinable\UD@CheckWhetherLeadingExplicitSpaceB{%
  \long\def\UD@CheckWhetherLeadingExplicitSpaceB#1 {%
    \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
    {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
    {\expandafter\expandafter\expandafter\UD@stopromannumeral
     \expandafter\expandafter\expandafter}%
     \expandafter\UD@secondoftwo\expandafter{\string}%
  }%
}%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%.............................................................................
%%   \UD@ExtractFirstArg{ABCDE} yields  {A}
%%
%%   \UD@ExtractFirstArg{{AB}CDE} yields  {{AB}}
%%
%% Due to \romannumeral-expansion the result is delivered after two 
%% expansion-steps/after "hitting" \UD@ExtractFirstArg with \expandafter
%% twice.
%%
%% \UD@ExtractFirstArg's argument must not be blank.
%% This case can be cranked out via \UD@CheckWhetherBlank before calling
%% \UD@ExtractFirstArg.
%%
%% Use frozen-\relax as delimiter for speeding things up.
%% I chose frozen-\relax because David Carlisle pointed out in
%% <https://tex.stackexchange.com/a/578877>
%% that frozen-\relax cannot be (re)defined in terms of \outer and cannot be
%% affected by \uppercase/\lowercase.
%%
%% \UD@ExtractFirstArg's argument may contain frozen-\relax:
%% The only effect is that internally more iterations are needed for
%% obtaining the result.
%%.............................................................................
\@ifdefinable\UD@RemoveTillFrozenrelax{%
  \expandafter\expandafter\expandafter\UD@Exchange
  \expandafter\expandafter\expandafter{%
  \expandafter\expandafter\ifnum0=0\fi}%
  {\long\def\UD@RemoveTillFrozenrelax#1#2}{{#1}}%
}%
\expandafter\UD@PassFirstToSecond\expandafter{%
  \romannumeral\expandafter
  \UD@PassFirstToSecond\expandafter{\romannumeral
    \expandafter\expandafter\expandafter\UD@Exchange
    \expandafter\expandafter\expandafter{%
    \expandafter\expandafter\ifnum0=0\fi}{\UD@stopromannumeral#1}%
  }{%
    \UD@stopromannumeral\romannumeral\UD@ExtractFirstArgLoop
  }%
}{%
  \newcommand\UD@ExtractFirstArg[1]%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  {\UD@stopromannumeral#1}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillFrozenrelax#1}}%
}%
%====================================================================
\@ifdefinable\UD@gobbletoexclam{\long\def\UD@gobbletoexclam#1!{}}%
\@ifdefinable\UD@ChooseDDigit{%
  \long\def\UD@ChooseDDigit#1!1!2!3!4!5!6!7!8!9!0!D!#2#3!!!!{#2}%
}%
\newcommand\UD@CollectDDigit[5]{%
  % #1 token to examine
  % #2 pending D
  % #3 digits gathered as probable argument of formatting-command
  % #4 formatting-command, takes 1 undelimited argument
  % #5 tokens forming the result gathered so far
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletoexclam#1!}%
  {%
    \UD@ChooseDDigit
    !#1!2!3!4!5!6!7!8!9!0!D!{\UD@firstoftwo}% digit 1
    !1!#1!3!4!5!6!7!8!9!0!D!{\UD@firstoftwo}% digit 2
    !1!2!#1!4!5!6!7!8!9!0!D!{\UD@firstoftwo}% digit 3
    !1!2!3!#1!5!6!7!8!9!0!D!{\UD@firstoftwo}% digit 4
    !1!2!3!4!#1!6!7!8!9!0!D!{\UD@firstoftwo}% digit 5
    !1!2!3!4!5!#1!7!8!9!0!D!{\UD@firstoftwo}% digit 6
    !1!2!3!4!5!6!#1!8!9!0!D!{\UD@firstoftwo}% digit 7
    !1!2!3!4!5!6!7!#1!9!0!D!{\UD@firstoftwo}% digit 8
    !1!2!3!4!5!6!7!8!#1!0!D!{\UD@firstoftwo}% digit 9
    !1!2!3!4!5!6!7!8!9!#1!D!{\UD@firstoftwo}% digit 0
    !1!2!3!4!5!6!7!8!9!0!#1!{\expandafter\UD@firstoftwo\UD@secondoftwo}% character D
    !1!2!3!4!5!6!7!8!9!0!D!{\expandafter\UD@secondoftwo\UD@secondoftwo}!!!!%neither D nor digit
  }{\expandafter\UD@secondoftwo\UD@secondoftwo}%%neither D nor digit
  {% digit
    \UD@CheckWhetherNull{#2}{%
      \UD@stopromannumeral\UD@DDigitReplaceloop{}{}{#4}{#5#1}%
    }{%
      \UD@stopromannumeral\UD@DDigitReplaceloop{#2}{#3#1}{#4}{#5}%
    }%
  }{%
    {% character D
      \UD@CheckWhetherNull{#2}{%
        \UD@PassFirstToSecond{#5}%
      }{%
        \UD@CheckWhetherNull{#3}{%
          \UD@PassFirstToSecond{#5#2}%
        }{%
          \UD@PassFirstToSecond{#5#4{#2#3}}%
        }%
      }%
      {\UD@stopromannumeral\UD@DDigitReplaceloop{#1}{}{#4}}%
    }{% neither D nor digit
      \UD@CheckWhetherNull{#2}{%
        \UD@PassFirstToSecond{#5#1}%
      }{%
        \UD@CheckWhetherNull{#3}{%
          \UD@PassFirstToSecond{#5#2#1}%
        }{%
          \UD@PassFirstToSecond{#5#4{#2#3}#1}%
        }%
      }%
      {\UD@stopromannumeral\UD@DDigitReplaceloop{}{}{#4}}%
    }%
  }%
}%
\newcommand\UD@DDigitReplaceloop[5]{%
  % #1 pending D
  % #2 digits gathered as probable argument of formatting-command
  % #3 formatting-command, takes 1 undelimited argument
  % #4 tokens forming the result gathered so far
  % #5 remaining token list to process
  \UD@CheckWhetherNull{#5}{%
    \UD@CheckWhetherNull{#1}{\UD@stopromannumeral#4#2}{%
      \UD@CheckWhetherNull{#2}{\UD@stopromannumeral#4#1}{\UD@stopromannumeral#4#3{#1#2}}%
    }%
  }{%
    \UD@CheckWhetherBrace{#5}{%
      \expandafter\UD@PassFirstToSecond\expandafter{\UD@firstoftwo{}#5}{%
        \expandafter\UD@PassFirstToSecond\expandafter{%
          \romannumeral
          \UD@CheckWhetherNull{#1}{%
            \UD@PassFirstToSecond{\UD@stopromannumeral#4#2}%
          }{%
            \UD@CheckWhetherNull{#2}{%
              \UD@PassFirstToSecond{\UD@stopromannumeral#4#1}%
            }{%
              \UD@PassFirstToSecond{\UD@stopromannumeral#4#3{#1#2}}%
            }%
          }%
          {%
            \expandafter\UD@PassFirstToSecond
            \expandafter{%
              \romannumeral
              \expandafter\expandafter\expandafter\UD@PassFirstToSecond
              \UD@ExtractFirstArg{#5}{\UD@DDigitReplaceloop{}{}{#3}{}}%
            }%
          }%
        }{%
          \UD@DDigitReplaceloop{}{}{#3}%
        }%
      }%
    }{%
      \UD@CheckWhetherLeadingExplicitSpace{#5}{%
        \expandafter\UD@PassFirstToSecond\expandafter{\UD@removespace#5}{%
          \UD@CheckWhetherNull{#1}{%
             \UD@PassFirstToSecond{#4 }%
          }{%
            \UD@CheckWhetherNull{#2}{%
              \UD@PassFirstToSecond{#4#1 }%
            }{%
              \UD@PassFirstToSecond{#4#3{#1#2} }%
            }%
          }%
          {\UD@DDigitReplaceloop{}{}{#3}}%
        }%
      }{%
        \expandafter\UD@PassFirstToSecond\expandafter{\UD@firstoftwo{}#5}{%
          \expandafter\UD@firstoftwo\expandafter{%
            \romannumeral
            \expandafter\expandafter\expandafter
            \UD@CollectDDigit\UD@ExtractFirstArg{#5}{#1}{#2}{#3}{#4}%
          }{}%
        }%
      }%
    }%
  }%
}%
\newcommand\SurroundDDigits[2]{%
  \romannumeral\UD@DDigitReplaceloop{}{}{#1}{}{#2}%
}%
\makeatother


\documentclass{article}

\begin{document}

\begin{verbatim}
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\test
\expandafter\expandafter\expandafter{%
  \SurroundDDigits{\textbf}{%
    Axfd D12FF 23{AxfdD12FF2 3{Axf dD12FF23{}f\relax 
    D114 6ffasdfa}f\relax D1146ff asdfa}f\relax 
    D1146ffa sdfa%
  }%
}%
{\ttfamily \meaning\test}
\end{verbatim}

\noindent yields:
\vskip\partopsep\vskip\topsep

\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\test
\expandafter\expandafter\expandafter{%
  \SurroundDDigits{\textbf}{%
    Axfd D12FF 23{AxfdD12FF2 3{Axf dD12FF23{}f\relax D114 6ffasdfa}f\relax D1146ff asdfa}f\relax D1146ffa sdfa%
  }%
}%
{\ttfamily \meaning\test}

\vskip\partopsep\vskip\topsep
\noindent\hrule
\vskip\partopsep\vskip\topsep

\begin{verbatim}
\newcommand\MyFontCommand[1]{{\footnotesize\emph{\textbf{#1}}}}%
\SurroundDDigits{\MyFontCommand}{%
  Axfd D12FF 23{AxfdD12FF2 3{Axf dD12FF23{}f\relax 
  D114 6ffasdfa}f\relax D1146ff asdfa}f\relax 
  D1146ffa sdfa%
}%
\end{verbatim}

\noindent yields:
\vskip\partopsep\vskip\topsep

\newcommand\MyFontCommand[1]{{\footnotesize\emph{\textbf{#1}}}}%
\SurroundDDigits{\MyFontCommand}{%
  Axfd D12FF 23{AxfdD12FF2 3{Axf dD12FF23{}f\relax 
  D114 6ffasdfa}f\relax D1146ff asdfa}f\relax 
  D1146ffa sdfa%
}%

\end{document}

在此处输入图片描述

答案3

使用 Steven B. Segletes 的想法,即在遇到字符时启动\Cotetest-循环,您可以执行类似这样的操作,它不会将格式应用于-sequences 的每个字符,但在收集整个序列后应用格式:\CotetrueDD<decimal digits>

\documentclass{article}
\usepackage{tokcycle,xcolor}
\Characterdirective{\ifx D#1\Cotetest{D}{0}\else\addcytoks{#1}\fi}
\newcommand\Cotetest[2]{%
  % #1 - character-token D + digits gathered so far for formatting
  % #2 - flag: = 0 -> no digits are gathered yet / 
  %            =/= 0 -> some digits were gathered in previous iterations
  \tcpeek\z
  \ifx0\z\Cotetrue{#1}\else
  \ifx1\z\Cotetrue{#1}\else
  \ifx2\z\Cotetrue{#1}\else
  \ifx3\z\Cotetrue{#1}\else
  \ifx4\z\Cotetrue{#1}\else
  \ifx5\z\Cotetrue{#1}\else
  \ifx6\z\Cotetrue{#1}\else
  \ifx7\z\Cotetrue{#1}\else
  \ifx8\z\Cotetrue{#1}\else
  \ifx9\z\Cotetrue{#1}\else
  \ifnum#2=0 \addcytoks{#1}\else\addcytoks{\bgroup\footnotesize\emph{\textbf{#1}}\egroup}\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
\newcommand\Cotetrue[1]{%
  % #1 character-token D + digits gathered so far for formatting
  \tcpop\z
  \expandafter\expandafter\expandafter\Cotetest
  \expandafter\expandafter\expandafter{\expandafter\exchange\expandafter{\z}{#1}}{1}%
}%
\newcommand\exchange[2]{#2#1}
% Let \one be an implicit character token denoting 1 of catcode 12(other):
\let\one=1
\begin{document}
\tokencyclexpress
D\one7
D7\one1C2
D93
\textcolor{red}{D123abc}
Dcf
D 
D\today
\endtokencyclexpress
\end{document}

在此处输入图片描述

一种变体,它将隐式字符生成为不被视为数字的数字:

\documentclass{article}
\usepackage{tokcycle,xcolor}
\Characterdirective{\ifx D#1\Cotetest{D}{0}\else\addcytoks{#1}\fi}
\newcommand\Cotetest[2]{%
  % #1 - character-token D + digits gathered so far for formatting
  % #2 - flag: = 0 -> no digits are gathered yet / 
  %            =/= 0 -> some digits were gathered in previous 
  \tcpeek\z
  \ifx0\z\Cotetrue{#1}{#2}{0}\else
  \ifx1\z\Cotetrue{#1}{#2}{1}\else
  \ifx2\z\Cotetrue{#1}{#2}{2}\else
  \ifx3\z\Cotetrue{#1}{#2}{3}\else
  \ifx4\z\Cotetrue{#1}{#2}{4}\else
  \ifx5\z\Cotetrue{#1}{#2}{5}\else
  \ifx6\z\Cotetrue{#1}{#2}{6}\else
  \ifx7\z\Cotetrue{#1}{#2}{7}\else
  \ifx8\z\Cotetrue{#1}{#2}{8}\else
  \ifx9\z\Cotetrue{#1}{#2}{9}\else
  \ifnum#2=0 \addcytoks{#1}\else\addcytoks{\bgroup\footnotesize\emph{\textbf{#1}}\egroup}\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
\newcommand\Cotetrue[3]{%
  % #1 - character-token D + digits gathered so far for formatting
  % #2 - flag: = 0 -> no digits are gathered yet / 
  %            =/= 0 -> some digits were gathered in previous
  % #3 - explicit digit character-token to compare for cranking out
  %      implicit character tokens
  \tcpop\z
  \begingroup
  \def\tempa{#3}%
  \expandafter\endgroup\csname @\ifx\tempa\z first\else second\fi oftwo\endcsname
  {%
    \expandafter\expandafter\expandafter\Cotetest
    \expandafter\expandafter\expandafter{\expandafter\exchange\expandafter{\z}{#1}}{1}%
  }{%
   \ifnum#2=0 
      \addcytoks[2]{\expandafter\exchange\expandafter{\z}{#1}}%
   \else
      \addcytoks[2]{\expandafter\exchange\expandafter{\z}{\bgroup\footnotesize\emph{\textbf{#1}}\egroup}}%
   \fi
  }%
}%
\newcommand\exchange[2]{#2#1}
% Let \one be an implicit character token denoting 1 of catcode 12(other):
\let\one=1
\begin{document}
\tokencyclexpress
D\one7
D7\one1C2
D93
\textcolor{red}{D123abc}
Dcf
D 
D\today
\endtokencyclexpress
\end{document}

在此处输入图片描述

相关内容