在将命令作为另一个命令的参数传递,描述了将 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
或以其他方式使用修改后的字符串。
笔记在任何情况下(xstring
或xparse
方法),如果你需要改变文字 $
变成24
,不要用\$
,而只是$
。
答案3
引用 xstring 文档解释了为什么您的方法不起作用:
当使用 \fullexpandarg 激活完全扩展模式时,参数在被宏读取之前会先用 \edef 进行扩展。
此包中的宏并非纯粹可扩展的,即它们不能放入 \edef 的参数中。嵌套宏也是不可能的。
所以这可能对你没什么帮助,但你可能要找点什么。如果你能提出问题,从现在开始可能会更容易帮助你。