我正在编写一个宏,根据 LaTeX 报告中的字符串值来格式化字符串。我遇到了一个问题,其中包含美元符号 (\$) 的字符串会导致错误。这是一个最小工作示例:
\documentclass{article}
\usepackage{color}
\usepackage{xstring}
\newcommand{\ChgFmt}[1]{\IfSubStr{#1}{-}{{\color{red} #1}}{ {\color{green} #1}}}
\begin{document}
This number is printed in green: \ChgFmt{1\%}
This number is printed in red: \ChgFmt{-1\%}
\end{document}
如果将上面的 1\% 替换为 \$1 million,则我会收到消息“TeX 容量超出”,并且不会产生任何输出。我读到一种解决方案是将上面的 \newcommand 的参数括在 \ensuremath 中,如下所示:
\documentclass{article}
\usepackage{color}
\usepackage{xstring}
\newcommand{\ChgFmt}[1]{\ensuremath{\IfSubStr{#1}{-}{{\color{red} #1}}{ {\color{green} #1}}}}
\begin{document}
This number is printed in green: \ChgFmt{\$1 million}
\end{document}
但是,这会将“百万”格式化为数学符号而不是字符串。我尝试按照下面的建议使用@gobble,但我的代码还有额外的复杂性,因为我使用了动态变量。具体来说,这是一个最小示例:
\documentclass{article}
\usepackage{color}
\newcommand{\FirstDollarAmount}{\$1 million}
\newcommand{\SecondDollarAmount}{-\$1 million}
\newcommand{\inputnum}[2]{\expandafter\csname #1#2\endcsname}
\makeatletter
\newcommand{\ChgFmt}[1]{{\@ifnextchar{-}{\color{red}$-$\@gobble}{\color{green}}#1}}
\makeatother
\begin{document}
This number should be printed in green: \ChgFmt{\inputnum{First}{DollarAmount}}
This number should be printed in red: \ChgFmt{\inputnum{Second}{DollarAmount}}
\end{document}
虽然输出没有错误,但两个数字都打印成绿色。还有其他想法吗?
答案1
您需要\fullexpandarg
,但\$
和\text
无法幸免;后一个命令是在普通类型中设置“百万”所必需的。
因此,我首先中\$
和并使它们在测试期间\text
等同;在测试决定是否遵循真实路径或错误路径后进行替换。\relax
其他宏可能需要类似的处理;并不是\%
因为它非常强大且能够存活下来\edef
。
\documentclass{article}
\usepackage{amsmath}
\usepackage{color}
\usepackage{xstring}
\makeatletter
\newcommand{\ChgFmt}[1]{%
\ensuremath{%
\begingroup\fullexpandarg
\let\$\relax \let\text\unexpanded
\IfSubStr{#1}{-}
{\endgroup\@firstoftwo}
{\endgroup\@secondoftwo}%
{\begingroup\color{red}#1\endgroup}
{\begingroup\color{green}#1\endgroup}%
}%
}
\makeatother
\newcommand{\FirstDollarAmount}{\$1\text{ million}}
\newcommand{\SecondDollarAmount}{-\$1\text{ million}}
\newcommand{\inputnum}[2]{\expandafter\csname #1#2\endcsname}
\begin{document}
This number is printed in green: \ChgFmt{\$1 \text{ million}}
This number is printed in red: \ChgFmt{-\$1 \text{ million}}
This number should be printed in green: \ChgFmt{\inputnum{First}{DollarAmount}}
This number should be printed in red: \ChgFmt{\inputnum{Second}{DollarAmount}}
\end{document}