如果参数以 # 开头,则将其吞噬

如果参数以 # 开头,则将其吞噬

我的问题来自 pandoc 和 markdown,但它与这些工具没有直接关系,而是通过一些 tex 宏编程“定制”生成的 pdf,所以我认为它是主题。

我正在用 markdown 语法编写文档,并通过 pandoc 将其转换为 LaTeX(和 html)。此文档包含一些网站的超链接。当我用 markdown 编写时:

See [this web](http://tex.stackexchange.com/)

它在 TeX 中生成:

See \href{http://tex.stackexchange.com/}{this web}

我想实现一个版本\href,除了在pdf中插入超链接外,它还会制作一个包含url的脚注,这对文档的打印版本更有用。我这样做了如下:

\let\oldhref=\href
\renewcommand{\href}[2]{\oldhref{#1}{#2}\footnote{\url{#1}}}

到目前为止一切顺利。它按预期运行。

现在的问题是,pandoc 还支持对文档中其他部分的“内部引用”。如果我有一个名为的部分Related work,pandoc 会自动生成一个内部锚点名称related-work,这样我就可以在我的 markdown 源中写入:

# Related work
Blah blah

# Another section
See [section about related work](#related-work)

上述 markdown 翻译为:

\hyperdef{}{related-work}{\section{Related work}\label{related-work}}

Blah blah

\section{Another section}

See \href{\#related-work}{section about related work}.

现在我的问题是,我重新定义\href这个内部引用时还会产生一个脚注,这显然是不必要的。脚注只显示文本#related-work,这对读者来说毫无用处,此外单击脚注文本会产生错误(而显示网址的其他脚注则工作正常)。

所以,我的问题是:我该如何重新定义\href

  1. 如果其第一个参数的第一个字符是#(或者是\#?),则它表现为标准\href(无脚注)
  2. 否则,它就像我的重新定义一样工作(内部超链接加上脚注排版目标网址)。

答案1

以下是一个条件句的想法

\iffirsttoken{<tokenlist>}{<token>}{<true>}{<false>}

使用 kernel 命令\@car。您可以在重新定义中使用它来\href测试第一个标记是否是\#

\documentclass{article}

\makeatletter
% this is found in latex.ltx:
% \def\@car#1#2\@nil{#1}
\def\iffirsttoken#1#2{%
  % define \@first@token to be the once expanded \@car of the first argument
  % i.e. the first token or balanced group:
  \expandafter\def\expandafter\@first@token\expandafter{\@car#1\@nil}%
  % test if the expansion of \@first@token is the same as #2:
  \expandafter\ifx\@first@token#2\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}

\usepackage{hyperref}

\let\oldhref\href
\renewcommand{\href}[2]{%
  \oldhref{#1}{#2}%
  \iffirsttoken{#1}{\#}{}{\footnote{\url{#1}}}%
}

\begin{document}

\hyperdef{}{related-work}{\section{Related work}\label{related-work}}

\iffirsttoken{foo}{f}{true}{false}% true

\iffirsttoken{\#related-work}{\#}{true}{false}% true

\iffirsttoken{this web}{\#}{true}{false}% false

\href{http://tex.stackexchange.com}{this web}

\href{\#related-work}{section about related work}

\end{document}

在此处输入图片描述

答案2

如果你想要从字符串的第一个位置删除 \#,则可以使用此命令轻松完成

\newcommand\strippound[1]{\expandafter\ifx\expandafter\##1\else#1\fi}

现在去掉 # 就完全是另一回事了,因为它是 TeX 中的特殊字符


经过一天的思考,我想到了一个办法,如何从字符串的第一个字符中去掉真正的 # 符号(注意,不是 \# 符号)。我认为,这是一个有意义的结果,因为 TeX 操作 # 字符非常困难。最后,答案出奇地简单。答案如下:

\documentclass{article}

\catcode `#=11
\edef\lb{#}
\catcode `#=6
\newcommand\strippound[1]{\if\lb#1\else#1\fi}

\begin{document}
\noindent
\strippound{#This string began with a pound sign}\\    \strippound{This string did not begin with a pound sign}
\end{document}

在此处输入图片描述

答案3

我不确定是否要编辑我之前的回答或添加这个新回答。但这似乎足够独特,值得在讨论中添加一个新帖子。如果小组认为下面的帖子不合适,我会删除它。

在我之前的回答中,我发现了如何从字符串的开头位置删除 catcode 6 #。这一分水岭开辟了从输入流中操纵 catcode 6 # 符号的一系列新方法。

在以下这段代码中,除了删除前导磅号(我现在称之为 \leadingpound)之外,我还生成了将所有 catcode 6 # 符号转换为 \# 符号的例程,以及从输入流中删除所有 catcode 6 磅号的例程

正如 JLDiaz 在上一个回答中指出的那样,该技术开辟了处理“危险人物”的新方法。我希望您同意这是一个开始。

\documentclass{article}
\usepackage{ifnextok}

\catcode `#=11
\edef\lb{#}
\catcode `#=6
\newcommand\leadingpound[1]{\if\lb#1\else#1\fi}

\makeatletter
\def\@stringend{$}
\def\convertpounds#1{\scan@Block#1\@stringend}
\def\scan@Block{\IfNextToken\@stringend{\@gobble}%
  {\IfNextToken\@sptoken{ \conv@rt{\scan@Block}}%
  {\conv@rt{\scan@Block}}}}

\def\conv@rt#1#2{\if\lb#2\#\else#2\fi#1}

\def\strippounds#1{\process@Block#1\@stringend}
\def\process@Block{\IfNextToken\@stringend{\@gobble}%
  {\IfNextToken\@sptoken{ \bl@t{\process@Block}}%
  {\bl@t{\process@Block}}}}

\def\bl@t#1#2{\if\lb#2\else#2\fi#1}
\makeatother

\begin{document}
\noindent
The following commands work on raw (catcode 6) pound signs
(not backslash-pound symbols).
\vspace{1ex}\\
Started as \convertpounds{#ABC}.  After leadingpound:
  \leadingpound{#ABC}
  $\leftarrow$ No \# may follow lead \#\\
Started as \convertpounds{#A#BC#}.  After convertpounds:
  \convertpounds{#A#BC#}
  $\leftarrow$ These are $\backslash$\#\\
Started as \convertpounds{#A#BC#}.  After strippounds:
  \strippounds{#A#BC#}
\end{document}

在此处输入图片描述

相关内容