吞噬每个出现的 \mypath../

吞噬每个出现的 \mypath../

\mypath../有没有一种巧妙的方法,可以使用 TeX 的文本处理功能从输入中删除所有文本实例?ifthen下面的方法可行,但似乎有点繁重。此外,我正在寻找一种可行的解决方案命令\documentclass

\documentclass{scrartcl}
\usepackage{ifthen}

\newcommand{\mypath}[3]{%
  \ifthenelse{\equal{#1#2#3}{../}}{}{#1#2#3}%
}

\begin{document}
  Gobble: \mypath../

  Don't gobble: \mypath.ab
\end{document}

答案1

这是一种可扩展的方法:

\long\def\mypath#1#2#3{\mypathaux../#1#2#3../}
\long\def\mypathaux../#1../{%
  \if\relax\detokenize{#1}\relax
    \expandafter\mypathgobble
  \else
    #1
  \fi}
\long\def\mypathgobble#1#2#3{}

\mypath吸收了接下来的三个标记并\mypathaux以一种奇怪的方式进行调用;让我们看看两种主要情况:

  1. \mypath../变成\mypathaux../../../

  2. \mypath xyz变成\mypathaux../xyz../

\mypathaux仅具有参数,从 的第一次出现../到 的第二次出现的所有标记。在情况 1 中,两次出现之间没有任何内容,因此#1为空。在情况 2 中,#1xyz

该宏现在测试是否#1为空(这是 H. Oberdiek 巧妙的伎俩);如果是,它调用\mypathgobble吞噬../主标记列表中剩余的;否则它就返回#1

在某些情况下可能需要的\fi类似方法是#1

\makeatletter
\newcommand\mypath[3]{\@mypath../#1#2#3../}
\long\def\@mypath../#1../{%
  \if\relax\detokenize{#1}\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi\@gobblethree{#1}}
\providecommand\@gobblethree[3]{}
\makeatother

这使用了 LaTeX 内核的功能,而以前的宏则没有。

让我们看看这两种情况。\mypath xyz我们得到

\@mypath../xyz../

并且测试返回 false,所以我们只剩下

\expandafter\@secondoftwo\fi\@gobblethree{xyz}

作用\expandafter\fi(它只是消失),留下

\@secondoftwo\@gobblethree{xyz}

所以\@secondoftwo最终得到xyz。在这种情况下\mypath../我们得到

\@mypath../../../

并且测试返回 true;这样

\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi\@gobblethree{}../

(只有前两个../在模式匹配中消失)。第一个\expandafter作用于\elsewhich 会导致匹配之前的所有内容\fi消失:

\@firstoftwo\@gobblethree{}../

现在我们得到了

\@gobblethree../

什么也没有留下。

相关内容