以变​​量作为分隔符的分离函数

以变​​量作为分隔符的分离函数

如何/可能改变此实现\xSplit以便分隔符是在定义时(\edef以某种方式?)或在实际使用命令时填写的变量?

%based on the following code
%TeX by Topic unknown number of arguments p105
%\White(K1a,Q2b,3c,P4d)%

\def\endpiece{xxx}% a sentinel that ends the lists of inputs 
\def\dosomethingwithsplitofpiece#1{*#1} 

举个简单的例子:在它前面放一颗星星

\def\sep{,} 

\xSplit我想在像的定义中使用它,其中各部分之间的分隔符\def\xSplit#1\sep{...}\sep:以下示例中的逗号。我当然可以使用函数\xSplitComma来拆分逗号和 \xSplitSemicolon ...,其中这些分隔符是硬连线的,但我希望它是一个变量,这样我只需定义 \xSplit一次,其中\sep\dosomethingwithsplitofpiece是按照我的意愿定义的额外的问题:是否可以\sep 在内部重新定义\dosomethingwithsplitpiece,以便在例如\xSplit 上拆分,;而不是,例如在找到一定数量的 之后或递归地拆分,其中首先用逗号分隔,然后这些块因此用分号分隔,依此类推。

\def\xSplit#1,{\def\temp{#1}% replace , by \sep
\ifx\temp\endpiece% no more to process
\else% 
   \dosomethingwithsplitofpiece{#1}%
   \expandafter\xSplit%
\fi%
}%

\def\Split(#1){#1 transforms into \xSplit#1,xxx,% >-- how this comma as a variable 
                                                % that can be changed if necessary??
}%  

这是一个以逗号分隔的数字列表,作为示例,然后在每次块分割前放置一个星号

\Split(4,5,6,7,9,10,11)
 % \Split(4,5,6;7,9,10;11){1} 

\bye

答案1

您必须每次重新定义拆分宏,因为您不知道调用时分隔符是什么:

\def\Split(#1){%
  \makexSplit
  \expandafter\xSplit\expandafter{\sep}{#1}%
}
\def\xSplit#1#2{\xxSplit#2#1\endpiece#1}

\def\makexSplit{%
  \begingroup\edef\x{\endgroup\def\noexpand\xxSplit####1\sep}%
  \x{%
    \def\temp{##1}%
    \ifx\temp\endpiece
    \else
      \dosomethingwithsplitofpiece{##1}%
      \expandafter\xxSplit
    \fi
  }%
}
\def\endpiece{\endpiece} % don't use \endpiece in the wild!
\def\dosomethingwithsplitofpiece#1{*#1} 

\def\sep{,}

\Split(4,5,6,7,9,10,11)

\def\sep{;}

\Split(4;5;6;7;9;10;11)

\bye

在此处输入图片描述

唯一不能出现在列表中的标记是\endpiece。请注意,在文档中除了在此上下文(或与终止符类似的上下文)之外使用它会导致无限循环。

线条

  \begingroup\edef\x{\endgroup\def\noexpand\xxSplit####1\sep}%
  \x{%

可能会被替换为

  \expandafter\def\expandafter\xxSplit\expandafter##\expandafter1\sep{%

如果\sep预计包含不存在的标记\edef


使用更高级别的解决方案expl3(但这需要 e-TeX):

\input expl3-generic

\ExplSyntaxOn

\seq_new:N \l_lampter_split_arg_seq

\cs_new_protected:Npn \Split ( #1 )
 {
  \seq_set_split:NVn \l_lampter_split_arg_seq \sep { #1 }
  \seq_map_inline:Nn \l_lampter_split_arg_seq
   {
    \dosomethingwithsplitofpiece{##1}
   }
 }
\cs_generate_variant:Nn \seq_set_split:Nnn { NV }
\ExplSyntaxOff

\def\dosomethingwithsplitofpiece#1{*#1}

\def\sep{,}

\Split(4,5,6,7,9,10,11)

\def\sep{;}

\Split(4;5;6;7;9;10;11)

\bye

\Split将使用当前的值来\sep分割参数。然后\seq_map_inline:Nn处理循环。

答案2

您可以定义\declaresplitsep宏,并\split使用所需的分隔符重新定义宏:

\def\dosomethingwithsplitofpiece#1{*#1}

\def\declaresplitsep#1{%
   \def\split(##1){\splitA##1#1#1}%
   \def\splitA##1#1{\ifx#1##1#1\else\dosomethingwithsplitofpiece{##1}\expandafter\splitA\fi}%
}

\declaresplitsep,
\split(4,5,6,7,9,10,11)

\declaresplitsep;
\split(4;5;6;7;9;10;11)

\end

这似乎有点神秘。所以,我展示了我如何编写这个宏。首先,我\split用具体的分隔符(逗号)定义了:

\def\split(#1){\splitA#1,,}%
\def\splitA#1,{\ifx,#1,\else \dosomethingwithsplitofpiece{#1}\expandafter\splitA \fi}

其次,我将这段代码打包到并将\def\declaresplitsep#1{...}所有标记加倍#,最后用 替换逗号#1

相关内容