如何将宏参数扩展为字符串,删除所有空格,然后在 \NewDocumentCommand 宏定义中附加和添加字符串?

如何将宏参数扩展为字符串,删除所有空格,然后在 \NewDocumentCommand 宏定义中附加和添加字符串?

我想将宏参数扩展为字符串,删除所有空格,然后在 \NewDocumentCommand 宏定义中附加和添加字符串。

这是我使用 LuaLaTeX 的 MWE。

在此处输入图片描述

\documentclass[oneside,DIV=12]{scrbook}

\usepackage{scrhack}
\usepackage{mathtools, amssymb}
\usepackage[warnings-off={mathtools-colon,mathtools-overbracket}]{unicode-math}
    \setmathfont{Latin Modern Math}
\usepackage{xparse}
\usepackage{xpatch}

    % \ExpandArg (https://tex.stackexchange.com/a/515425)
\ExplSyntaxOn
\cs_new_protected:Nn \__user_expand_arg:n
 {
  \tl_set:No \ProcessedArgument { #1 }
 }
\cs_set_eq:NN \ExpandArg \__user_expand_arg:n
\ExplSyntaxOff

    % \RemoveSpaces (https://tex.stackexchange.com/a/87510)
\makeatletter
\def\RemoveSpaces#1{\zap@space#1 \@empty}
\makeatother

    % \foo, \foobar, and \xy
\NewDocumentCommand{\foo}{>{\ExpandArg} m}{%
    \renewcommand{\foobar}{+\RemoveSpaces{#1}.}
    \xpatchcmd{\foobar}{+x-y.}{++xx--yy..}{}{} % check if there's a '+x-y.' w/o any spaces, then replace it with '++xx--yy..'
    \foobar % print the output
}
\newcommand{\foobar}{}
\newcommand{\xy}{ x - y }

\begin{document}\KOMAoptions{DIV=current}\Large%
    \[\foo{\xy}\] % if all the spaces are removed, it should print the output as '++xx--yy..' and not '+x-y.'
\end{document}

为什么这不起作用?我认为问题可能是我不太明白\RemoveSpaces作品。

谢谢。

答案1

\zap@space通过完全扩展起作用,因此必须在\edef\expanded上下文中使用。您的\foobar的内容不会在 内扩展\renewcommand,因此它将与您在那里填写的内容完全相同。宏\xy被扩展一次,留下␣x␣-␣y␣,然后您将其分配给\foobar,它将包含+\RemoveSpaces{␣x␣-␣y␣}.现在与您的搜索字符串 不匹配的内容+x-y.

但请注意,它\zap@space有几个历史限制:它必须在完全扩展上下文中使用,并且它可能会删除您想要保留的括号。

下面定义了一个参数处理器,它可以消除所有空间而不受这些限制,因此您可以#1在其中简单地使用\renewcommand

\documentclass[oneside,DIV=12]{scrbook}

\usepackage{scrhack}
\usepackage{xparse}
\usepackage{xpatch}

    % \ExpandArg (https://tex.stackexchange.com/a/515425)
\ExplSyntaxOn
\cs_new_protected:Nn \__user_expand_arg:n
 {
  \tl_set:No \ProcessedArgument { #1 }
 }
\cs_set_eq:NN \ExpandArg \__user_expand_arg:n
\cs_new_protected:Npn \__user_arg_zap_spaces:n #1
  {
    \tl_set:Nn \ProcessedArgument {#1}
    \tl_remove_all:Nn \ProcessedArgument { ~ }
  }
\cs_set_eq:NN \ArgZapSpaces \__user_arg_zap_spaces:n
\ExplSyntaxOff

    % \foo, \foobar, and \xy
\NewDocumentCommand{\foo}{>{\ArgZapSpaces}>{\ExpandArg} m}{%
    \renewcommand{\foobar}{+#1.}
    \xpatchcmd{\foobar}{+x-y.}{++xx--yy..}{}{} % check if there's a '+x-y.' w/o any spaces, then replace it with '++xx--yy..'
    \foobar % print the output
}
\newcommand{\foobar}{}
\newcommand{\xy}{ x - y }

\begin{document}\KOMAoptions{DIV=current}\Large%
    \[\foo{\xy}\] % if all the spaces are removed, it should print the output as '++xx--yy..' and not '+x-y.'
\end{document}

在此处输入图片描述


为了完整性,\zap@space工作原理如下:

\zap@space定义为

\def\zap@space#1 #2{#1\ifx#2\@empty\else\expandafter\zap@space\fi#2}

因此,它将所有内容读取到空格处#1,并将其输出。此外,它还读取一个标记(或括号组,将由此取消括号)并将其与\@empty(这是您的中的结束标记\RemoveSpaces)进行比较。如果#2不是,则调用\@empty \zap@space自身。#2在末尾重新插入(如果是,它将\@empty扩展为空,因此不会造成任何影响)。所采用的方法只能在完全扩展的情况下起作用,因为#1总是在下一次调用之前放置\zap@space,因此我们不能从左侧扩展直到\zap@space完成(除了在无意义的情况下,#1只会扩展为空)。

相关内容