是否有一个技巧可以“静态地”集成给定字符串中的参数,然后在另一个命令中使用该字符串,然后处理该参数?
就像是 :
\edef\mystring{Hello #1 !} % this code does not work, of course
\newcommand\mydynamicstring[1]{\mystring}
可以这样做:
\mydynamicstring{world} % "Hello world"
答案1
是的,这是可能的:
%! TEX program = lualatex
\documentclass{article}
\begin{document}
\edef\mystring{\unexpanded{Hello #1 !}}
% equivalently
\def\mystring{Hello ##1 !}
% either do this (use \expanded to inject the content of \mystring into inside `\newcommand` before executing `\newcommand`)
\expanded{\noexpand\newcommand\noexpand\mydynamicstring[1]{\mystring}}
\mydynamicstring{world}
% or (injection by parameter)
\def\tmp#1{
\renewcommand\mydynamicstring[1]{#1}
}
\expandafter\tmp\expandafter{\mystring}
\mydynamicstring{world}
\end{document}
但考虑到代码最终会变得多么复杂(而且参数数量通常不固定),更简单的方法是将所有参数传递(复制)给子命令,\mystring
如 egreg 所建议的那样。它不会太长,而且更明确。
(为了在 Python 中进行比较,如果您想在另一个命令中使用某个函数,最好明确传递参数,而不是将值分配给全局变量等。)
请注意,将 TeX 代码视为“字符串”并不完全正确,因为每个字符都有一个同样重要的“类别代码”。
答案2
您可以使用##
而不是#
。
\documentclass{article}
\makeatletter
\NewDocumentCommand{\newdynamiccommand}{mO{0}m}{%
\expandafter\@newdynamiccommand\expandafter{#3}{#1}{#2}%
}
\newcommand{\@newdynamiccommand}[3]{%
\newcommand{#2}[#3]{#1}%
}
\makeatother
\newcommand\mystring{Hello ##1!}
\newdynamiccommand{\mydynamicstring}[1]{\mystring}
\begin{document}
\mydynamicstring{World}
\end{document}
您可以使用不同的方法#
。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\newdynamicstring}{mm}
{
\tl_clear_new:N #1
\tl_set:Nn #1 { #2 }
}
\NewDocumentCommand{\newdynamiccommand}{mO{0}m}
{
\brabant_dyncom:nnV { #1 } { #2 } #3
}
\cs_new_protected:Nn \brabant_dyncom:nnn
{
\newcommand{#1}[#2]{#3}%
}
\cs_generate_variant:Nn \brabant_dyncom:nnn { nnV }
\ExplSyntaxOff
\newdynamicstring\mystring{Hello #1!}
\newdynamiccommand{\mydynamicstring}[1]{\mystring}
\begin{document}
\mydynamicstring{World}
\end{document}