对空的扩展宏参数进行安全测试?

对空的扩展宏参数进行安全测试?

我怎样才能以安全的方式进行测试(即不保留令牌,如上所述这里) 如果扩展宏参数为空?

答案1

你可以使用一个\romannumeral技巧:

\if\relax\detokenize\expandafter{\romannumeral-`\Q#1}\relax

后面缺失的空格`\Q将触发扩展#1(当然是在宏替换之后)。由于此扩展在第一个不可扩展的标记处结束,因此这应该是您想要的。

但是前导空格将被忽略。

\def\notempty{\relax}
\def\perhapsempty{\empty}

\if\relax\detokenize\expandafter{\romannumeral-`\Q\empty}\relax
  \message{EMPTY}
\else
  \message{NOT EMPTY}
\fi

\if\relax\detokenize\expandafter{\romannumeral-`\Q\notempty}\relax
  \message{EMPTY}
\else
  \message{NOT EMPTY}
\fi

\if\relax\detokenize\expandafter{\romannumeral-`\Q\perhapsempty}\relax
  \message{EMPTY}
\else
  \message{NOT EMPTY}
\fi

\if\relax\detokenize\expandafter{\romannumeral-`\Q\space}\relax
  \message{EMPTY}
\else
  \message{NOT EMPTY}
\fi

This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014) (preloaded format=pdftex)
 restricted \write18 enabled.
entering extended mode
(./tsanempty.tex EMPTY NOT EMPTY EMPTY EMPTY)

如果您不需要可扩展性并且相信您传递的令牌是完全可扩展的,则可以使用\edef

\begingroup\edef\x{#1}\expandafter\endgroup\expandafter
\if\expandafter\relax\detokenize\expandafter{\x}\relax

例如,

\begingroup\edef\x{\empty}\expandafter\endgroup\expandafter
\if\expandafter\relax\detokenize\expandafter{\x}\relax
  \message{EMPTY}
\else
  \message{NOT EMPTY}
\fi

\begingroup\edef\x{\notempty}\expandafter\endgroup\expandafter
\if\expandafter\relax\detokenize\expandafter{\x}\relax
  \message{EMPTY}
\else
  \message{NOT EMPTY}
\fi

\begingroup\edef\x{\perhapsempty}\expandafter\endgroup\expandafter
\if\expandafter\relax\detokenize\expandafter{\x}\relax
  \message{EMPTY}
\else
  \message{NOT EMPTY}
\fi

\begingroup\edef\x{\space}\expandafter\endgroup\expandafter
\if\expandafter\relax\detokenize\expandafter{\x}\relax
  \message{EMPTY}
\else
  \message{NOT EMPTY}
\fi

将返回

EMPTY NOT EMPTY EMPTY NOT EMPTY

其实,an\expandafter是多余的,但是清晰度更好。

答案2

在此处输入图片描述

\documentclass{article}
\usepackage[T1]{fontenc}

\def\foo#1{\par \texttt{<\detokenize{#1}>} 
\expandafter\if\relax\detokenize\expandafter{\romannumeral0#1}\relax
\if X#1X%
empty\else
not empty\fi
\else
not empty\fi}

\begin{document}
\foo{}

\foo{ }

\foo{\empty}

\foo{{}}

\foo{\sqrt}

\foo{\csname @gobble\endcsname{hello}}

\end{document}

答案3

你试过 ifmtarg 包吗?它提供了宏

\@ifmtarg{<arg>}{<Code for arg empty>}
                {<Code for arg not empty>}

使用 texdoc ifmtarg 进行文档编写。

相关内容