我有一些用于格式化名称的代码。但是,ifempty
宏xifthen
无法检测xstring
宏(例如)的空输出。方法StrBetween
也是如此\equal {}
。我如何检测空输出StrBetween
?下面的代码出于某种原因编译并且不起作用。
\documentclass{article}
\usepackage{xstring}
\usepackage{xifthen}
\newcommand{\name}{John Doe}
\newcommand{\middleinitial}{%
\StrBetween{\name}{ }{.}
}
\newcommand{\test}{%
\ifthenelse{\isempty{\middleinitial}}%
{Whoo hoo!}%
{Not whoo hoo.}
}
\begin{document}
\test
\end{document}
有任何想法吗?
答案1
\middleinitial
是不可扩展的,因此你无法正确测试是否存在中间首字母\name
。您必须存储输出(中间首字母)第一的在末尾使用可选参数\StrBetween{<str>}{<from>}{<to>}[<macro>]
,然后你就可以检查是否为空参数:
\documentclass{article}
\usepackage{xstring}
\newcommand{\name}{John Doe}
\makeatletter
\newcommand{\middleinitial}{%
\StrBetween{\name}{ }{.}[\@middleinitial]%
}
\newcommand{\test}{%
\middleinitial% Find middle initial
% https://tex.stackexchange.com/q/53068/5764
\if\relax\detokenize\expandafter{\@middleinitial}\relax
Whoo hoo!% No middle initial
\else
Not whoo hoo.% A middle initial
\fi
}
\makeatother
\begin{document}
\test % Whoo hoo.
\renewcommand{\name}{John F. Doe}%
\test % Not whoo hoo!
\end{document}
答案2
沃纳已经解释过为什么\middleinitial
由于使用xstring
宏而无法扩展。
我提出了一种更短的方法来测试 是否为空,\middleinitial
即使用\ifblank
frometoolbox
包。仍然\expandafter
需要两个语句,但不需要 5 个语句。此外,我发现它比或etoolbox
更方便。ifthen
xifthen
\expandafter\ifblank\expandafter{\middleinitial}{true branch}{false branch}
是必要的,因为\ifblank
不会扩展它的第一个参数,即没有\expandafter
宏“看到”\middleinitial
但不知道该宏中存储的内容。在\ifblank
执行测试之前必须先将其扩展。
原\expandafter
语会先看\ifblank
,即它忽略\ifblank
first 并检测{
第一个参数的 。不幸的是,这不是我们想要的(而且无论如何也不可扩展),所以我们必须再次跳过{
,即
\expandafter\ifblank\expandafter{\middleinitial}{...}{...}
将允许 TeX/LaTeX '跳转'\ifblank
到第二个\expandafter
,跳转{
并\middleinitial
扩展该序列 - 完成后,TeX 继续\ifblank{expanded version of \middleinitial}{...}{...}
并最终执行测试。
\documentclass{article}
\usepackage{xstring}
\usepackage{etoolbox}
\newcommand{\name}{John C. Doe}
\newcommand{\othername}{John Doe}
\newcommand{\testinitial}[3]{%
\begingroup
\StrBetween{#1}{ }{.}[\middleinitial]%
\expandafter\ifblank\expandafter{\middleinitial}{#2}{#3}%
\endgroup
}
\begin{document}
\testinitial{\name}{Whoo hoo!}{Not whoo hoo.}
\testinitial{\othername}{Whoo hoo!}{Not whoo hoo.}
\end{document}
答案3
谢谢@Werner 和 @ChristianHupfer!根据您的解决方案,我找到了另一个解决方案,xstring
它看起来很简洁:
\documentclass{article}
\usepackage{xstring}
\newcommand{\name}{John Doe}
\makeatletter
\newcommand{\middleinitial}{%
\StrBetween{\name}{ }{.}[\@middleinitial]%
}
\newcommand{\test}{%
\middleinitial % Find middle initial
\IfStrEq{\@middleinitial}{}%
{Whoo hoo!}%
{Not whoo hoo.}%
}
\makeatother
\begin{document}
\test % Whoo hoo.
\renewcommand{\name}{John F. Doe}%
\test % Not whoo hoo!
\end{document}
我在这里发布了一个后续问题,其中有一个与\IfStrEqual
和相关的更令人烦恼的扩展问题\IfSubStr
(关联)如果有人能帮忙的话。