8

For filename "DoctorStrange.tex", I want to print the substring "Strange" dynamically inside the file. The following command does not work; what am I doing wrong?

\documentclass{article}
\usepackage{xstring}
\begin{document}

\StrBehind{\jobname}{Doctor}

\end{document}
2
  • 2
    Use the starred version \StrBehind*, see section 3.4 of the package docu.
    – Troy
    Commented Oct 1, 2017 at 4:09
  • Woah! That solved my problem! Thankyou so much!! Commented Oct 1, 2017 at 8:36

2 Answers 2

11
% File name: DoctorStrange.tex
\documentclass{article}
\usepackage{xstring}
\begin{document}
    \StrBehind*{\jobname}{Doctor}% <---- Note the starred variant
\end{document}

gives

strange

Certain TeX commands like \jobname (as is in your case) expand into strings made of characters with catcodes 12 and 10, whereas ordinary letters from the alphabet is given catcode 11.

The xstring package commands, as noted in the package documentation (Section 3.4, under Catcode and Starred Macros), take catcodes into account during comparisons, and so Doctor is not found in the \jobname because they have different catcodes.

To solve this, xstring package provides a starred variant of its commands, in this case \StrBehind*{<strA>}{<strB>}, which detokenizes the two string arguments, and as the documentation puts it:

...everything is converted into chars with "harmless" catcodes.

which will then yield the desired result, as above.

1
  • is there any StrAfter?
    – alper
    Commented Jan 9, 2023 at 11:57
6

The characters in \jobname are “stringified”, which roughly means that your input Doctor (where the characters are letters) is not the same as the Doctor in \jobname (where they are nonletters).

You can use the “agnostic” version of \StrBehind or a similar category code agnostic function of 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}

enter image description here

In the optional argument you can specify the name of a macro that will contain the name. If you prefer that the text is treated as letters, for subsequent comparisons, you can use \tl_set_rescan:Nnn (actually a variant thereof):

\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}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .