可扩展的字符串替换

可扩展的字符串替换

我正在尝试定义一个宏

\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} 

在此处输入图片描述

相关内容