使用 xstring 格式化动态变量中的字符串

使用 xstring 格式化动态变量中的字符串

我需要格式化由单独程序中设置的动态变量生成的字符串,以便生成 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原因有二:

  1. \if在测试之前完全扩展其参数(这很重要,因为-在内部嵌入了几个扩展#1);并且

  2. “积极”测试会从参数中剥离前导标记,这正是 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} 

在此处输入图片描述

相关内容