对每个单词/字符应用操作

对每个单词/字符应用操作

有一些相关问题:

对每个单词应用宏

迭代空格分隔的列表

如何重复字符串中的所有字符?

但我发现的每篇帖子都要求具体的东西,很难理解哪些部分才是对所有字符/单词应用特定操作的实际需要。假设我们有一个,\newcommand\command1[1]{do something}我们想对每个字符应用这个,\newcommand\command2[1]{do something}我们想对每个单词应用哪个。我们该怎么做呢?

答案1

使用expl3:两个命令都有第二个参数,它是处理字符或单词的模板。

在最后一种情况下,我们需要##1嵌套调用。

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\applytoeverychar}{mm}
 {
  \group_begin:
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_replace_all:Nnn \l_tmpa_tl { ~ } { \c_space_tl }
  \cs_set_protected:Nn \__masum_apply:n { #2 }
  \tl_map_function:NN \l_tmpa_tl \__masum_apply:n
  \group_end:
 }

\NewDocumentCommand{\applytoeveryword}{mm}
 {
  \group_begin:
  \seq_set_split:Nnn \l_tmpa_seq { ~ } { #1 }
  \cs_set_protected:Nn \__masum_apply:n { #2 }
  \seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { \__masum_apply:n { ##1 } }
  \seq_use:Nn \l_tmpb_seq { ~ }
  \group_end:
 }

\cs_new:Nn \__masum_apply:n {} % initialize

\ExplSyntaxOff

\begin{document}

\applytoeverychar{do something}{\textlangle #1\textrangle}

\applytoeveryword{do something}{\textlangle #1\textrangle}

\applytoeveryword{do something}{\textbar\applytoeverychar{#1}{\textlangle##1\textrangle}\textbar}

\end{document}

在此处输入图片描述

答案2

tokcycle包 (https://ctan.org/pkg/tokcycle) 设置为循环遍历输入的 token 流并依次处理每个 token。它具有宏和环境形式,并可辨别任何给定的 token 是被归类为“字符”、“组”、“宏”(控制序列)还是“空格”(隐式或显式)。这四个类别中的每一个都可以接收有关如何处理该类型 token 的指令。

常规方法是将处理过的标记收集到标记列表中\cytoks,然后存储起来,以后再重新使用。这种方法允许在执行宏之前收集宏并处理其参数。如果输入流中的宏实际上没有执行(假设它们只是被去标记化),则\cytoks可以绕过收集标记的这个阶段,并且可以动态输出标记。

在下面的 MWE 中,字符被设为红色并放在括号中,组内容用斜体表示(而组的标记则单独处理),宏用蓝色表示,空格用绿色可见空格表示。在这种情况下,使用 来\addcytoks收集标记\cytoks并不是必需的,因为宏不是执行的,而是被表示的(通过\string)。但是,我还是会收集它们,因为这是标记循环通常进行的方式。

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{tokcycle,xcolor}
\Characterdirective{\addcytoks{\textcolor{red}{(#1)}}}
\Groupdirective{\addcytoks{\itshape}\processtoks{#1}}
\Macrodirective{\addcytoks{\textcolor{cyan}{\string#1}}}
\Spacedirective{\addcytoks{\textcolor{green}{\textvisiblespace}}}

\begin{document}
\tokcyclexpress{This {is \today's} test.}
\the\cytoks

\end{document}

在此处输入图片描述

如果希望一次处理一个单词而不是一个字符,则必须在标记循环中构建逻辑以收集字符,并在遇到开始/结束组、宏和/或空格时转储它们。

因此,逻辑更加详细,但仍然简单明了。

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{tokcycle,xcolor}
\def\theword{}
\newcommand\dumpword{\if\relax\theword\relax\else
  \addcytoks{\textcolor{red}{(}}%
  \addcytoks[1]{\theword}%
  \addcytoks{\textcolor{red}{)}}\fi
  \def\theword{}}
\stripgroupingtrue
\Characterdirective{\expandafter\def\expandafter\theword\expandafter
  {\theword#1}}
\Groupdirective{\dumpword\groupedcytoks{%
  \addcytoks{\itshape}\processtoks{#1}\dumpword}}
\Macrodirective{\dumpword\addcytoks{\textcolor{cyan}{\string#1}}}
\Spacedirective{\dumpword\addcytoks{\textcolor{green}{\textvisiblespace}}}
\newcommand\wordprocessor[1]{%
  \tokcyclexpress{#1}%
  \dumpword
  \the\cytoks
}
\begin{document}
\wordprocessor{This {is \today's} test.}
\end{document}

在此处输入图片描述

在较新版本的 中tokcycle,提供了向前查看输入流中一个标记的功能(在以下 MWE 中,通过\tcpeek)。利用此功能,可以简化单词收集的逻辑,只需确定输入流的下一个标记是否是另一个字符即可。

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{tokcycle,xcolor}
\def\theword{}
\newcommand\dumpword{%
  \addcytoks{\textcolor{red}{(}}%
  \addcytoks[1]{\theword}%
  \addcytoks{\textcolor{red}{)}}%
  \def\theword{}}
\newcommand\addtotheword[1]{%
  \expandafter\def\expandafter\theword\expandafter{\theword#1}%
  \tcpeek\z
  \ifcat A\z\else\ifcat0\z\else\dumpword\fi\fi
}
\Characterdirective{\addtotheword{#1}}
\Groupdirective{\addcytoks{\itshape}\processtoks{#1}}
\Macrodirective{\addcytoks{\textcolor{cyan}{\string#1}}}
\Spacedirective{\addcytoks{\textcolor{green}{\textvisiblespace}}}
\newcommand\wordprocessor[1]{%
  \tokcyclexpress{#1}%
  \the\cytoks
}
\begin{document}
\wordprocessor{This {is \today's} test.}
\end{document}

对于给定的输入流,此代码将产生与上述相同的结果。

相关内容