将宏(带参数)作为另一个宏的参数传递

将宏(带参数)作为另一个宏的参数传递

将命令作为另一个命令的参数传递,描述了将 TeX 宏作为方法调用的概念。就我而言,我尝试在调用结构中使用参数。下面的示例使用两次传递\StrSubstitute来替换我想要修改的字符:

\usepackage{xstring} % for StrSubstitute

\newcommand*{\changeslash}[1] {%
    \StrSubstitute{#1}{/}{5c}%
}
\newcommand*{\changedollars}[1] {%
    \StrSubstitute{#1}{\$}{24}%
}
\newcommand*{\changeboth}[1] {%
    \changeslash{\changedollars{#1}}%
}

我尝试过\expandafter在不同的地方添加,但是这个问题让我很困惑。

答案1

在此处输入图片描述

xstring替换不能通过扩展来工作,但它们需要扩展输入字符串,因此添加\expandafter并没有真正帮助。您需要使用可选参数,以便将替换后的字符串存储在临时宏中,然后您可以使用\expandafter扩展该宏来传递给第二个调用。此外,由于它以与 LaTeX 机制不完全一致的方式完全扩展其输入,因此\protect我需要\$保护 e-tex。

\documentclass{article}

\usepackage{xstring} % for StrSubstitute

\let\olddollar\$
\protected\def\${\olddollar}


\newcommand*{\changeslash}[1] {%
    \StrSubstitute{#1}{/}{5c}[\temp]%
}
\newcommand*{\changedollars}[1] {%
    \StrSubstitute{#1}{\$}{24}[\temp]%
}
\newcommand*{\changeboth}[1] {%
  \changedollars{#1}%
  \expandafter\changeslash\expandafter{\temp}%
}


\begin{document}


\changeslash{aaa/b\$bb}\temp


\changedollars{aaa/b\$bb}\temp


\changeboth{aaa/b\$bb}\temp

\end{document} 

答案2

该问题似乎依赖于您应该应用的两种设置:

\noexpandargs
\exploregroups

如果我给出你的定义并使用这些声明,从

\changeboth{A/B\$C}

我知道 LaTeX 打印

A5cB24C

这似乎是您所期望的。但是,您将无法检索修改后的字符串。如果您想将结果存储在宏中以供以后使用,则应使用其他方法。

\documentclass{article}
\usepackage{xstring} % for StrSubstitute

\newcommand*{\changeslash}[1]{%
    \StrSubstitute{#1}{/}{5c}[\temp]%
}
\newcommand*{\changedollars}[1]{%
    \StrSubstitute{#1}{\$}{24}[\temp]%
}
\newcommand*{\changeboth}[1]{%
  \changedollars{#1}%
  \expandafter\changeslash\expandafter{\temp}%
}

\begin{document}
\noexpandarg
\changeboth{A/B\$C}

\show\temp
\end{document}

这不会产生任何输出,但 TeX 会在终端上打印

> \temp=macro:
->A5cB24C.
l.18 \show\temp

并且可以自由使用更改后的字符串。这里\exploregroups不需要。


不同的方法是使用 LaTeX3 功能。

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
% Document commands
\NewDocumentCommand{\changeslash}{ m }
 {
  \baitisj_change_slash:n { #1 }
 }
\NewDocumentCommand{\changedollars}{ m }
 {
  \baitisj_change_dollars:n { #1 }
 }
\NewDocumentCommand{\printchangedstring}{}
 {
  \tl_use:N \l_baitisj_string_tl
 }
\NewDocumentCommand{\changeboth}{ m }
 {
  \baitisj_change_dollars:n { #1 }
  \baitisj_change_slash:V \l_baitisj_string_tl
 }

% Variables and functions
\tl_new:N \l_baitisj_string_tl
\cs_new_protected:Npn \baitisj_change_slash:n #1
 {
  \tl_set:Nn \l_baitisj_string_tl { #1 }
  \tl_replace_all:Nnn \l_baitisj_string_tl { / } { 5c }
 }
\cs_new_protected:Npn \baitisj_change_dollars:n #1
 {
  \tl_set:Nn \l_baitisj_string_tl { #1 }
  \tl_replace_all:Nnn \l_baitisj_string_tl { \$ } { 24 }
 }
\cs_generate_variant:Nn \baitisj_change_slash:n { V }

\ExplSyntaxOff

\begin{document}

\changeboth{A/B\$C}
\printchangedstring

\end{document}

将其扩展到更多替换的方案似乎很明确。这取决于您的应用程序使用\printchangedstring或以其他方式使用修改后的字符串。

笔记在任何情况下(xstringxparse方法),如果你需要改变文字 $变成24,不要用\$,而只是$

答案3

引用 xstring 文档解释了为什么您的方法不起作用:

当使用 \fullexpandarg 激活完全扩展模式时,参数在被宏读取之前会先用 \edef 进行扩展。

此包中的宏并非纯粹可扩展的,即它们不能放入 \edef 的参数中。嵌套宏也是不可能的。

所以这可能对你没什么帮助,但你可能要找点什么。如果你能提出问题,从现在开始可能会更容易帮助你。

相关内容