我需要格式化由单独程序中设置的动态变量生成的字符串,以便生成 LaTeX 报告。具体来说,如果变量具有负值(以减号开头),我希望将该变量显示为红色没有减号。这是一个最小工作示例:
\documentclass{article}
\usepackage{amsmath}
\usepackage{color}
\usepackage{xstring}
\makeatletter
\newcommand{\ChgFmt}[1]{%
\begingroup\fullexpandarg
\let\$\relax \let\text\unexpanded
\IfSubStr{#1}{-}
{\endgroup\@firstoftwo}
{\endgroup\@secondoftwo}%
{\begingroup\color{red}#1\endgroup}
{\begingroup\color{green}#1\endgroup}%
}
\makeatother
% Output from variables file
\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{\inputnum{First}{DollarAmount}}
This number should be printed in red, without the minus sign: \ChgFmt{\inputnum{Second}{DollarAmount}}
\end{document}
我曾尝试使用 \@gobble 以及 \StrSubstitute,但由于动态变量中存在 \$,它们均未产生预期的结果。
我还希望能够更灵活地格式化字符串。例如,我想在正数前面添加一个 $\uparrow$,在负数前面添加一个 $\downarrow$。Steven B. Segletes 提供的解决方案很优雅,但不够灵活,无法添加这些(至少是天真的):
\documentclass{article}
\usepackage{amsmath,xcolor}
\def\ChgFmt#1{\textcolor{red}{\if-#1\else\textcolor{green}{$\uparrow$#1}\fi}}
% Output from variables file
\newcommand{\FirstDollarAmount}{\$1\text{ million}}
\newcommand{\SecondDollarAmount}{-\$1\text{ million}}
\newcommand{\inputnum}[2]{\csname #1#2\endcsname}
\begin{document}
This number is printed in green: \ChgFmt{\inputnum{First}{DollarAmount}}
This number should be printed in red, without the minus sign: \ChgFmt{\inputnum{Second}{DollarAmount}}
\end{document}
还有其他想法吗?提前感谢您的帮助。
答案1
如果不使用 ,这一行解析是否足够xstring
?这个问题实际上是为构造量身定制的,\if-#1
原因有二:
\if
在测试之前完全扩展其参数(这很重要,因为-
在内部嵌入了几个扩展#1
);并且“积极”测试会从参数中剥离前导标记,这正是 OP 想要的。
我将字符串设置为红色,并使用\if-#1...\else...\fi
构造来决定参数的前导标记是否为-
。如果发现前导-
,则将其剥离,同时将剩余的文本保留为红色。如果没有找到\if
前导,则整个参数以绿色输出。-
\documentclass{article}
\usepackage{amsmath,xcolor}
\def\ChgFmt#1{\textcolor{red}{\if-#1\else\textcolor{green}{#1}\fi}}
% Output from variables file
\newcommand{\FirstDollarAmount}{\$1\text{ million}}
\newcommand{\SecondDollarAmount}{-\$1\text{ million}}
\newcommand{\inputnum}[2]{\csname #1#2\endcsname}
\begin{document}
This number is printed in green: \ChgFmt{\inputnum{First}{DollarAmount}}
This number should be printed in red, without the minus sign: \ChgFmt{\inputnum{Second}{DollarAmount}}
\end{document}
更新
为了处理 OP 的修订表述,可以在临时框内进行测试,然后将其丢弃,但在此之前不能\gdef
是所需的结果(绿色\uparrow
或红色\downarrow
)放入临时变量中。然后,添加该临时变量,然后进行初始解决方案中描述的先前测试。
\documentclass{article}
\usepackage{amsmath,xcolor}
\def\ChgFmt#1{\setbox0=\hbox{%
\if-#1\gdef\tmp{\textcolor{red}{$\downarrow$}}\else%
\gdef\tmp{\textcolor{green!60!black}{$\uparrow$}}\fi%
}\tmp%
\textcolor{red}{\if-#1\else\textcolor{green!60!black}{#1}\fi}%
}
% Output from variables file
\newcommand{\FirstDollarAmount}{\$1\text{ million}}
\newcommand{\SecondDollarAmount}{-\$1\text{ million}}
\newcommand{\inputnum}[2]{\csname #1#2\endcsname}
\begin{document}
This number is printed in green: \ChgFmt{\inputnum{First}{DollarAmount}}
This number should be printed in red, without the minus sign: \ChgFmt{\inputnum{Second}{DollarAmount}}
\end{document}
答案2
以下是对前一个解决方案的修改,它使用了不同的解决方法:
\documentclass{article}
\usepackage{amsmath}
\usepackage{color}
\usepackage{xstring}
\makeatletter
\newcommand{\ChgFmt}[1]{%
\ensuremath{%
\begingroup
\expandarg
\protected@edef\temp{#1}%
\IfSubStr{\temp}{-}
{\StrSubstitute{\temp}{-}{}[\temp]\@firstoftwo}
{\@secondoftwo}%
{\color{red}{\downarrow}\temp\endgroup}
{\color{green}{\uparrow}\temp\endgroup}%
}%
}
\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}