重写为最小非工作示例:
\documentclass{article}
\makeatletter
\usepackage{xstring}
\usepackage{xparse}
\newcommand\textfromcase[1]{%
\IfEqCase{#1}{% for the purposes of this example:
{0}{AB} % \textfromcase[0] expands to AB
{1}{CD} % \textfromcase[1] expands to CD
% and many more lines of this kind.
}}
\newcommand{\EscSubstitute}[2]{\expandafter\StrSubstitute\expandafter{\x}{#1}{#2}[\x]}
\newcommand\substitute[1]{{%
\noexpandarg% because I otherwise get weird error messages.
\StrSubstitute{#1}{BC}{CB}[\x]% replacements for example.
\EscSubstitute{PQ}{QP}% many more lines of this kind.
\x}}
\newcommand{\concatenate}[1]{%
\substitute{\@for \el:=#1\do{\textfromcase{\el}}}%
}
\makeatother
\begin{document}
\substitute{ABCD} = ACBD.
\concatenate{1,0} = CDAB.
\concatenate{0,1} $\neq$ ACBD!
\end{document}
\concatenate{0,1}
应该扩展为ACBD
但是却扩展为ABCD
。
答案1
\substitute
在使用此命令之前,您需要完全扩展的参数。这可以安排,但不能使用\@for
不可扩展的映射。由于您已经在使用,所以xparse
我只会在中写入它expl3
。有关详细信息,请参阅代码注释:
\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
% User command taking ones comma-list argument
\NewDocumentCommand \concatenate { > { \SplitList { , } } m }
{
% Use an x-type expansion with an expandable argument to force
% expansion here
\user_substitute:x
{
\tl_map_function:nN {#1} \user_text_from_case:n
}
}
% A simple document-level wrapper around a code-level function
\NewDocumentCommand \substitute { m }
{ \user_substitute:n {#1} }
% The code-level substitution command is built to be flexible
\cs_new_protected:Npn \user_substitute:n #1
{
\group_begin:
\tl_set:Nn \l__user_tmp_tl {#1}
\tl_map_inline:nn
{
% A list of pairs for substitution: could be in a separate
% tl or comma list depending on requirements
{ { BC } { CB } }
{ { PQ } { QP } }
}
{ \__user_substitute_aux:nn ##1 }
\exp_last_unbraced:NV \group_end:
\l__user_tmp_tl
}
\cs_generate_variant:Nn \user_substitute:n { x }
\cs_new_protected:Npn \__user_substitute_aux:nn #1#2
{ \tl_replace_all:Nnn \l__user_tmp_tl {#1} {#2} }
\tl_new:N \l__user_tmp_tl
% An expandable case function to do first replacements
% Again, the list itself could be in a separate variable if required
\cs_new:Npn \user_text_from_case:n #1
{
\str_case:nn {#1}
{
{ 0 } { AB }
{ 1 } { CD }
}
}
% For outdated expl3 installations
\cs_if_exist:NF \str_case:nn
{
\cs_new:Npn \str_case:nn #1#2
{ \prg_case_str:nnn {#1} {#2} }
}
\ExplSyntaxOff
\begin{document}
\substitute{ABCD} = ACBD.
\concatenate{1,0} = CDAB.
\concatenate{0,1} $\neq$ ACBD!
\end{document}