我正在尝试定义一个宏
\formatstr{\mystring}{(string empty)}{the string is: #1}
(string empty)
当为空时\mystring
(例如通过 etoolbox 判断)扩展为\csdefempty
,否则扩展为the string is: \mystring
。
例如,我可以写
\newcommand*\formatstr[3]{%
\def\fmt##1{#3}%
\ifdefempty#1{#2}{\fmt{#1}}%
}
它按我想要的方式工作,除了它\formatstr
本身由于\def
分配而无法扩展。
有没有其他方法可以以可扩展的方式用替换#1
的第三个参数?\formatstr
\mystring
编辑:让我尝试更清楚地解释一下我想做的事情
使用etoolbox
我可以输入如下内容
\ifdefempty{\mystring}{(empty string)}{the string \mystring\ is funny}
但如果我必须写的话,这会变得很乏味
\ifdefempty{\mystringwithaverylongname}{(empty string)}{the string \mystringwithaverylongname\ is long}
所以我希望能够写的是
\formatstr{\mystringwithaverylongname}{(empty string)}{some string #1 is nice}
也许
\formatstr{\mystringwithaverylongname}{(empty string)}{i've heard that :str is interesting}
我想知道是否可以用第一个参数的内容替换第三个参数中的#1
(或)?:str
答案1
你需要一个包装器来\ifdefempty
充当参数处理器。例如:
\def\myifdefempty#1#2#3:str#4|{%
\ifdefempty{#1}{#2}{#3#1#4}%
}
完整最小示例:
\documentclass{article}
\usepackage{etoolbox}
\usepackage{hyperref}
\newcommand*{\formatstr}[3]{%
\myifdefempty{#1}{#2}#3|%
}
\def\myifdefempty#1#2#3:str#4|{%
\ifdefempty{#1}{#2}{#3#1#4}%
}
\begin{document}
\tableofcontents
\def\mystring{}
\section{\formatstr{\mystring}{an empty string}{the string :str is funny}}
\def\mystring{`a'}
\section{\formatstr{\mystring}{an empty string}{the string :str is funny}}
\end{document}
答案2
通常的习惯用法是这样的
\makeatletter
\begingroup
\lccode`\!=0
\lowercase{\endgroup
\newcommand*\formatstr[3]{%
\if!#1!%
\expandafter\@firstofthree
\else
\expandafter\@secondoftwo
\fi{#2}{#3}{#1}}}
\long\def\@firstofthree#1#2#3{#1}
\makeatother
\def\foo{}
\typeout{A: \formatstr\foo{string is emty}{the string is: \fmt}}
\def\fmt#1{[[#1]]}
\def\foo{hello}
\typeout{B: \formatstr\foo{string is emty}{the string is: \fmt}}
\stop
产生输出(以\typeout
表明它是可扩展的
A: string is emty
B: the string is: [[hello]]
或者这个版本不需要\fmt
辅助宏。
此处,如注释中所述,语法是
\fmtstring\token{empty}{non-empth-pre}{non-empty-post}
用于empty
空的情况和扩展
non-empth-pre\token non-empty-post
在非空情况下使用。
A: string is empty
B: the string is: [hello]
来自稍微简单一点的代码:
\makeatletter
\begingroup
\lccode`\!=0
\lowercase{\endgroup
\newcommand*\formatstr[4]{%
\if!#1!%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi{#2}{#3#1#4}}}
\makeatother
\def\foo{}
\typeout{A: \formatstr\foo{string is empty}{the string is: [}{]}}
\def\foo{hello}
\typeout{B: \formatstr\foo{string is empty}{the string is: [}{]}}
\stop
答案3
我猜这就是约瑟夫赖特所说的,这对我来说听起来很合逻辑,但我认为我没有很好地理解 OP。\ifdefempty
可以以一种相当昂贵的方式扩展。
\documentclass{article}
\usepackage{etoolbox}
\newcommand*\formatstr[3]{\ifdefempty{#1}{#2}{#3#1}}
\newcommand*\bformatstr[3]{\ifblank{#1}{#2}{#3{#1}}}
\begin{document}
\def\fmt#1{[[#1]]}
\def\foo{}
\def\vgap{\par\bigskip}
\textbf{Case A1}: \formatstr\foo{string is empty}{the string is: \fmt}
\vgap
\textbf{Case A2}: \bformatstr{}{string is empty}{the string is: \fmt}
\vgap
\def\foo{hello}
\textbf{Case B1}: \formatstr\foo{string is empty}{the string is: \fmt}
\vgap
\textbf{Case B2}: \bformatstr{hello}{string is empty}{the string is: \fmt}
\end{document}