我在这个问题上浪费了大部分下午的时间,但还是搞不清楚。我准备了一个 MWE 来演示这个问题。在我的\displaylink
命令中,我调用\href{raw_url}{anchor}
(来自包hyperref
),但我想用另一个命令构建 raw_url,\createurl
该命令使用其中一个xstring
实用程序来操纵其参数。
在 MWE 中,有两个版本的\createurl
,一个没有命令 from xstring
,另一个\createurlx
有命令 ( )。如果您注释掉标有“fails”的行,并取消注释标有“works”的行,您会发现所有三个命令(\createurl
、\createurlx
和\displaylink
)都可以正常工作。但是,如果您注释掉“works”行并取消注释“fails”行,这意味着\displaylink
您调用的 from 调用\createurlx
了对\StrGobbleLeft
from 的调用xstring
,那么一切都会停止工作。所以问题似乎是这两个命令的嵌套。为什么,我不知道。
顺便说一句,我目前的解决方法是,如果我将 放在 里面\StrGobbleLeft
,事情也会起作用\displaylink
,但我不想这样做,因为 是\createurlx
一个在其他地方也使用的命令。(当然,您会意识到,这些操作在这里已经为 MWE 的目的进行了简化——它们在实际文档中不那么简单。)
\documentclass{article}
\usepackage{hyperref}
\usepackage{xstring}
\newcommand{\createurl}[1]{
http://www.foobar.com/documents/#1.pdf
}
\newcommand{\createurlx}[1]{
\StrGobbleLeft{#1}{1}[\chopped]
http://www.foobar.com/documents/\chopped.pdf
}
\newcommand{\displaylink}[1]{
% \href{\createurl{#1}}{\mbox{#1}} % works
\href{\createurlx{#1}}{\mbox{#1}} % fails
}
\begin{document}
The generated url looks like this: \createurl{my-stuff}.
The chopped url looks like this: \createurlx{my-stuff}.
The calling code wants to display a hyperlink: \displaylink{my-stuff}.
\end{document}
失败原因:
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian) (preloaded format=pdflatex)
restricted \write18 enabled.
entering extended mode
(./mwe2.tex
LaTeX2e <2017-04-15>
Babel <3.18> and hyphenation patterns for 84 language(s) loaded.
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo))
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-hyperref.sty
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-generic.sty))
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texlive/texmf-dist/tex/generic/ifxetex/ifxetex.sty)
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/auxhook.sty)
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/kvoptions.sty)
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def)
(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/hyperref.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty))
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/rerunfilecheck.sty))
(/usr/share/texlive/texmf-dist/tex/generic/xstring/xstring.sty
(/usr/share/texlive/texmf-dist/tex/generic/xstring/xstring.tex)) (./mwe2.aux)
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/gettitlestring.sty))
(./mwe2.out) (./mwe2.out)
! TeX capacity exceeded, sorry [input stack size=5000].
\Hy@href {->\hyper@normalise
\href@ {
l.25 ...o display a hyperlink: \displaylink{stuff}
.
! ==> Fatal error occurred, no output PDF file produced!
Transcript written on mwe2.log.
编辑:正如@egreg在评论中正确推测的那样,这不是我真正需要的字符串操作。真正的操作需要将输入转换
2010-x03-y10
为2010x3y10
,也就是说删除连字符和任何前导零---然后添加常量前缀和后缀。我毫不费力地将其编码为xstring
操作序列并将结果存储在命令名称中(\chopped
我的MWE的),但我无法“将获得的字符串交给\href
”(如果可能的话,请使用普通的Latex---但下面的@Herbert告诉我不是这样)。
答案1
如果不想expl3
使用任何功能,我建议先申请\StrGobbleLeft
,\displaylink
然后再申请\chopped
。无论如何\StrGobbleLeft
,宏仍然可以应用\createurlx
。
\StrGobbleLeft
与几乎所有xstring
不可扩展的宏一样,因为它对输入字符串进行“严重”操作(“分配”)并且具有可选参数——这是不可扩展的,因此不会出现在\href
。
\documentclass{article}
\usepackage{xstring}
\usepackage{hyperref}
\newcommand{\displaylink}[1]{%
\StrGobbleLeft{#1}{1}[\chopped]%
\href{http://www.foobar.com/documents/\chopped.pdf}{\mbox{#1}}
}
\begin{document}
The calling code wants to display a hyperlink: \displaylink{my-stuff}.
\end{document}
答案2
\StrGobbleLeft
不能在这样的参数中使用。如果你真的只想从 expl3 中删除一个可以使用的字符\tl_tail:n
,这是可扩展的:
\documentclass{article}
\usepackage{hyperref}
\usepackage{expl3}
\newcommand{\createurl}[1]{
http://www.foobar.com/documents/#1.pdf
}
\ExplSyntaxOn
\newcommand{\createurlx}[1]
{
http://www.foobar.com/documents/\tl_tail:n{#1}.pdf
}
\ExplSyntaxOff
\newcommand{\displaylink}[1]{%
\href{\createurlx{#1}}{\mbox{#1}}%
}
\begin{document}
The generated url looks like this: \createurl{my-stuff}.
The chopped url looks like this: \createurlx{my-stuff}.
The calling code wants to display a hyperlink: \displaylink{my-stuff}.
\end{document}
答案3
\documentclass[a4paper]{article}
\usepackage[margin=1cm]{geometry}
\usepackage{hyperref}
\newcommand{\createurl}[1]{%
http://www.foobar.com/documents/#1.pdf%
}
\newcommand\createurlx[1]{\createURLX#1!!}
\def\createURLX#1#2!!{%
http://www.foobar.com/documents/#2.pdf%
}
\newcommand{\displaylink}[1]{%
\href{\createurlx{#1}}{\mbox{#1}}%
}
\begin{document}
The generated url looks like this: \createurl{my-stuff}.
The chopped url looks like this: \createurlx{my-stuff}.
The calling code wants to display a hyperlink: \displaylink{my-stuff}.
\end{document}