此代码崩溃是因为我将宏包含tmp
在label
命令中。阅读此论坛,尤其是脆弱命令和坚固命令之间有什么区别?,我以为\protect
我放在前面的\tmp
应该可以解决问题,但事实并非如此。有人能解释一下如何让它工作吗?非常感谢您的任何建议
\documentclass{amsart}
\usepackage{soul}
\usepackage{xstring}
\begin{document}
\def\tmp{fig:\StrBefore{file.png}{.}}
\tmp
\begin{figure}
\caption{nothing}
\label{\protect\tmp}
%\label{\tmp}
\end{figure}
\end{document}
答案1
答案2
的宏xstring
通常不可扩展,但这里需要它。因此,我将其改为listofitems
,它会产生可扩展的结果。
\documentclass{amsart}
\usepackage{soul}
\usepackage{listofitems}
\begin{document}
\setsepchar{.}
\readlist\fileroot{file.png}
\edef\tmp{fig:\fileroot[1]}
\tmp
\begin{figure}
\caption{nothing}
\label{\tmp}
\end{figure}
I refer to figure \ref{fig:file}
\end{document}
这是一个甚至不需要的版本listofitems
:
\documentclass{amsart}
\usepackage{soul}
\newcommand\fileroot[1]{\filerootaux#1.\relax}
\def\filerootaux#1.#2\relax{#1}
\begin{document}
\edef\tmp{fig:\fileroot{file.png}}
\tmp
\begin{figure}
\caption{nothing}
\label{\tmp}
\end{figure}
I refer to figure \ref{fig:file}
\end{document}
答案3
的参数\label
应该是最终变成字符串的东西,但\StrBefore
最终变成打印某些字符的说明,这是一件非常不同的事情。
这更简单,除非您的文件名中可以包含多个句点。
\documentclass{article}
\makeatletter
\newcommand{\stripext}[1]{\strip@ext#1.\@nil}
\def\strip@ext#1.#2\@nil{#1}
\makeatother
\begin{document}
\stripext{file.png}
\label{\stripext{file.png}}
\stripext{filenoext}
\label{\stripext{filenoext}}
\end{document}
诀窍是使用带有分隔参数的宏。如果我们这样做\stripext{file.png}
,我们会得到
\strip@ext file.png.\@nil
并且宏\strip@ext
将使用#1
任何出现的直到第一个.
;在这种情况下它是file
。
在的情况下\stripext{filenoext}
,我们得到
\strip@ext filenoext.\@nil
一切也都很好。在第一种情况下#2
是png.
,在第二种情况下它是空的;但第二个参数被简单地丢弃了。
.aux
上述代码中的文件将包含
\relax
\newlabel{file}{{}{1}}
\newlabel{filenoext}{{}{1}}
所以你看它正如预期的那样。