使用数字和可选字母解析参数

使用数字和可选字母解析参数

如何定义一个宏,它接受由数字和选修的字母,然后根据字母进行分支?
由于这是现有包的扩展,最好不要使用任何包或 LaTeX3;此外,由于语法尚未定义,您可以使用字母在数字后面或前面来实现答案,使用任何您想要的分隔符(没有更好)。

\documentclass{article}

\def\myparse#1{...} % or \newcommand{\myparse}[1]{...}

% Suppose the letter has to be after the number with no separator,
% and the command branches on letters "b", "m", "e" to represent
% the beginning, middle or end of a year.

\begin{document}
\myparse{2004b} % Should print "Beginning of 2004"
\myparse{2005}  % Should print "2005"
\myparse{2005m} % Should print "2005" too
\myparse{2006e} % Should print "End of 2006"
\end{document}

答案1

在此处输入图片描述

\documentclass{article}

\makeatletter
\def\myparse#1{\afterassignment\xmyparse\@tempcnta#1\relax}
\def\xmyparse#1\relax{\csname myparsexx#1\endcsname}
\def\myparsexxb{Beginning of \the\@tempcnta}
\def\myparsexx{\the\@tempcnta}
\def\myparsexxm{\the\@tempcnta}
\def\myparsexxe{End of \the\@tempcnta}
\makeatother

% Suppose the letter has to be after the number with no separator,
% and the command branches on letters "b", "m", "e" to represent
% the beginning, middle or end of a year.

\begin{document}
\myparse{2004b} % Should print "Beginning of 2004"

\myparse{2005}  % Should print "2005"

\myparse{2005m} % Should print "2005" too

\myparse{2006e} % Should print "End of 2006"
\end{document}

答案2

您可以在语法上自由发挥,允许键出现在年份之前或之后(实际上,键可以在任何地方出现多次;出现的最后一个字母将设置行为)。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\myparse}{m}
 {
  \astrinus_myparse:n { #1 }
 }

\tl_new:N \l_astrinus_myparse_year_tl
\tl_new:N \l_astrinus_myparse_key_tl

\cs_new_protected:Npn \astrinus_myparse:n #1
 {
  \tl_clear:N \l_astrinus_myparse_year_tl
  \tl_clear:N \l_astrinus_myparse_key_tl
  \tl_map_inline:nn { #1 } { \astrinus_add_token:n { ##1 } }
  \astrinus_print:
 }

\cs_new_protected:Npn \astrinus_add_token:n #1
 {
  \tl_if_in:nnTF { 0123456789 } { #1 }
   {
    \tl_put_right:Nn \l_astrinus_myparse_year_tl { #1 }
   }
   {
    \tl_set:Nn \l_astrinus_myparse_key_tl { #1 }
   }
 }

\cs_new_protected:Npn \astrinus_print:
 {
  \str_case:Vn \l_astrinus_myparse_key_tl
   {
    {b}{Beginning~of~}
    {e}{End~of~}
   }
  \tl_use:N \l_astrinus_myparse_year_tl
 }

\cs_generate_variant:Nn \str_case:nn { V }
\ExplSyntaxOff

\begin{document}

\myparse{2004b} % Should print "Beginning of 2004"

\myparse{b2004} % Should print "Beginning of 2004"

\myparse{2005}  % Should print "2005"

\myparse{2005m} % Should print "2005" too

\myparse{m2005} % Should print "2005" too

\myparse{2006e} % Should print "End of 2006"

\myparse{e2006} % Should print "End of 2006"

\end{document}

输入是逐个标记扫描的;数字在 中累积\l_astrinus_myparse_year_tl,而字母设置为\l_astrinus_myparse_key_tl。最后我们匹配\l_astrinus_myparse_key_tl可能的情况并执行适当的操作。

在此处输入图片描述

答案3

一种使用 e-TeX 提供可扩展解决方案的方法。其思想是循环输入,测试每个标记是否是数字。如果是,则保留它,如果不是,则假设我们已经到达数字的末尾并触发开始/中间/结束阶段。

\documentclass{article}
\usepackage[T1]{fontenc} % Just so \meaning looks right when printed

\makeatletter
\newcommand*\myparse[1]{%
  \myparse@auxi#1\q@tail\q@stop{}%
}
\newcommand*\myparse@auxi[1]{%
  \ifx\q@tail#1%
    \expandafter\myparse@end
  \fi
  \if\number\numexpr0#1-0#1\relax0%
    \expandafter\myparse@auxii
  \else
    \expandafter\myparse@auxiii
  \fi
    #1%
}
\newcommand*\myparse@auxii{}
\def\myparse@auxii#1#2\q@stop#3{%
  \myparse@auxi#2\q@stop{#3#1}%
}
\newcommand*\myparse@auxiii{}
\def\myparse@auxiii#1#2\q@stop{%
  \csname myparse@aux@#1\endcsname
}
\newcommand*\myparse@aux@b[1]{Beginning of #1}
\newcommand*\myparse@aux@m[1]{#1}
\newcommand*\myparse@aux@e[1]{End of #1}

\newcommand*\myparse@end{}
\def\myparse@end#1\q@stop#2{#2}

\def\q@tail{\q@tail}
\makeatother
\begin{document}
\myparse{2004b} % Should print "Beginning of 2004"

\myparse{2005}  % Should print "2005"

\myparse{2005m} % Should print "2005" too

\myparse{2006e} % Should print "End of 2006"

\edef\test{\myparse{2006e}}\meaning\test
\end{document}

从这个意义上来说,解决方案类似于大卫·卡莱尔除了数字检测是在宏中完成的而不是使用 TeX 原始分配之外。

相关内容