对于文件名“DoctorStrange.tex”,我想在文件内动态打印子字符串“Strange”。以下命令不起作用;我做错了什么?
\documentclass{article}
\usepackage{xstring}
\begin{document}
\StrBehind{\jobname}{Doctor}
\end{document}
答案1
% File name: DoctorStrange.tex
\documentclass{article}
\usepackage{xstring}
\begin{document}
\StrBehind*{\jobname}{Doctor}% <---- Note the starred variant
\end{document}
给出
某些 TeX 命令\jobname
(例如您的情况)扩展为由 catcode 为 12 和 10 的字符组成的字符串,而字母表中的普通字母则被赋予 catcode 11。
软件包xstring
命令,如包装文档(第 3.4 节,Catcode 和 Starred Macros 下),在比较过程中考虑 catcode,因此Doctor
在中找到它们,\jobname
因为它们具有不同的 catcode。
为了解决这个问题,xstring
包提供了其命令的星号变体,在本例中\StrBehind*{<strA>}{<strB>}
,它对两个字符串参数进行了去标记化,正如文档所述:
...所有内容都用“无害”的 catcode 转换成字符。
这样就会得到如上所述的期望结果。
答案2
中的字符\jobname
是“字符串化的”,这大致意味着您的输入(其中字符是字母)与中的(其中它们是非字母)Doctor
不同。Doctor
\jobname
您可以使用的“不可知”版本\StrBehind
或类似的类别代码不可知函数expl3
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\nodoctor}{o}
{
\tl_set:NV \l_tmpa_tl \c_sys_jobname_str
\regex_replace_once:nnN { \A Doctor } { } \l_tmpa_tl
\IfNoValueTF { #1 }
{
\tl_use:N \l_tmpa_tl
}
{
\tl_new:N #1
\tl_set_eq:NN #1 \l_tmpa_tl
}
}
\ExplSyntaxOff
\begin{document}
\nodoctor
\nodoctor[\thisname]
\texttt{\meaning\thisname}
\end{document}
在可选参数中,您可以指定将包含名称的宏的名称。如果您希望将文本视为字母,则对于后续比较,您可以使用\tl_set_rescan:Nnn
(实际上是其变体):
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\nodoctor}{o}
{
\tl_set:NV \l_tmpa_tl \c_sys_jobname_str
\regex_replace_once:nnN { \A Doctor } { } \l_tmpa_tl
\IfNoValueTF { #1 }
{
\tl_use:N \l_tmpa_tl
}
{
\tl_new:N #1
\tl_set_rescan:NnV #1 { } \l_tmpa_tl
}
}
\cs_generate_variant:Nn \tl_set_rescan:Nnn { NnV }
\ExplSyntaxOff
\begin{document}
\nodoctor
\nodoctor[\thisname]
\texttt{\meaning\thisname}
\newcommand*{\checkthisname}{Strange}
\ifx\thisname\checkthisname SUCCESS\else FAILURE\fi
\end{document}