# Pulling numbers out of a file name

A long time ago, I wanted to solve the problem where I would typeset my homework assignments, but copy the file "hw1.tex" to make "hw2.tex", and forget to change the title "Homework 1" at the top of the page.

So I wrote a function (that now I no longer 100% remember how it works, or maybe I got parts of it from a place like StackExchange and never did fully understand it):

\usepackage{substr}
\newcommand{\hwnum}{\BehindSubString{hw}{\scantokens\expandafter{\jobname\noexpand}}}


Now I can make Homework \hwnum the title. When I compile "hw1.tex", the title is "Homework 1", and when I compile "hw2.tex", the title becomes "Homework 2".

Minimal working example (assuming you first save it as a file with the appropriate name):

\documentclass{article}

\usepackage{substr}
\newcommand{\hwnum}{\BehindSubString{hw}{\scantokens\expandafter{\jobname\noexpand}}}

\begin{document}

This is Homework \hwnum.

\end{document}


These days, I have to typeset more than just homework assignments, so I'd like to have this be a bit more flexible.

1. It would be nicer, though not very important, if I didn't have to change the prefix "hw" in the command if I want to deal with filenames such as "day1.tex", "day2.tex", and so on.
2. What I really want is to extract more than one number: for example, "Lecture 7" and "Chapter 3" (or whatever) from a filename such as "ch3lec7.tex".
3. Putting these together, an ideal function would just be able to locate all the numbers in the filename, no matter which non-numbers they're separated by. The same function could pull out 3 and 7 whether it's given the filename "ch3lec7.tex" or "week3day7.tex".

What is a way for me to do at least #2, but also if possible #1 or #3?

The code below uses regular expressions from LaTeX3 to extract all of the numbers in the filename and then makes them available as \misha{1}, \misha{2}, .... There is no error checking so, for example, if you have \misha{100} in your document then this command will fail silently, doing nothing.

If you save the code below as the file ch3lec7.tex then run it you will get the output:

Here is the code:

\documentclass{article}

\usepackage{expl3}
\ExplSyntaxOn
\cs_generate_variant:Nn \regex_extract_all:nnN {nVN}
\seq_new:N \l_misha_seq
\regex_extract_all:nVN {\d+} \c_sys_jobname_str \l_misha_seq
\newcommand\misha[1]{\seq_item:Nn \l_misha_seq {#1}}
\ExplSyntaxOff

\begin{document}

Chapter \misha{1}, lecture \misha{2}.

\end{document}


The work is all done by the command \regex_extract_all:nVN, which puts all of the numbers in \jobname into an internal LaTeX3 sequence. (As egreg pointed out, LaTeX3 stores the filename in the string constant \c_sys_jobname_str.) The command \misha{k} prints the kth element of this sequence.

• When I try to compile this, I get the error Control sequence \regex_extract_all:nnN undefined. – Misha Lavrov Dec 10 '18 at 3:37
• @MishaLavrov I suspect that you need to update your latex distribution. I think that the regular expression machinery was added to LaTeX in mid 2017. The code above compiles fine for me. I am using TeX Live 2018. – Andrew Dec 10 '18 at 4:01
• Updating my LaTeX distribution was something of an adventure, but I got there in the end and now everything works. Thanks for the quick answer that does everything I hoped for! – Misha Lavrov Dec 10 '18 at 5:33

Off the cuff I can offer four macros:

1. \UD@ExtractDigitSequences{<arbitrary token sequence>}
This macro extracts all catcode-12-digit-sequences from <arbitrary token sequence>, nests each catcode-12-digit-sequence into curly braces.
2. \UD@ExtractKthDigitSequence{<number K>}{<arbitrary token sequence>}
This macro extracts the K-th catcode-12-digit-sequence from <arbitrary token sequence>.
3. \UD@ExtractDigitSequencesFromJobname
This macro extracts all catcode-12-digit-sequences from the expansion of \jobname, nests each catcode-12-digit-sequence into curly braces.
4. \UD@ExtractKthDigitSequenceFromJobname{<number K>}
This macro extracts the K-th catcode-12-digit-sequence from the expansion of \jobname.

Basically \UD@ExtractDigitSequences{<arbitrary token sequence>} and \UD@ExtractDigitSequencesFromJobname are wrappers for a recursive loop formed by the macro \UD@extractDigitSequencesLoop.

The gist of that recursive loop is:

\UD@extractDigitSequencesLoop processes three arguments:

The first argument denotes the (remaining) <arbitrary token-sequence>.
The second argument denotes the collection of brace-nested digit-sequences collected so far.
The third argument denotes the collection of digits collected so far for the current digit-sequence.

First the loop checks whether the (remaining) <arbitrary token-sequence> is empty.

If so, you are done and the second argument will be delivered and in case the third argument is not empty, it will also be delivered, nested in braces.

If not so, the loop will look at the first token of the (remaining) <arbitrary token-sequence>, hereby taking into account braces and spaces as cases that need special treatment.

In case of the first token of the (remaining) <arbitrary token-sequence> being both a non-brace-token and a non-digit-token, the current digit sequence in argument 3 is finished and, if not empty, can be nested in braces and attached to argument 2 before calling the loop again with that token removed from the (remaining) <arbitrary token-sequence>.

In case of the first token of the (remaining) <arbitrary token-sequence> being an opening-brace, the current digit sequence in argument 3 is finished and, if not empty, can be nested in braces and attached to argument 2. In this case we also need to attach to argument 2 the result of applying the entire routine on the brace-nested first component/on the leading undelimited argument of the (remaining) <arbitrary token-sequence> before calling the loop again with that undelimited argument removed from the (remaining) <arbitrary token-sequence>.

(This case is important only as long as it is about extracting from arbitrary token sequences: The expansion of the \jobname-primitive in any case does contain neither curly opening braces of category-code 1 nor closing braces of category code 2 but a collection of explicit character tokens that may contain explicit character tokens of category code 12(other but not with character code 32(space) and explicit character tokens of category code 10(space) and character code 32(space)=explicit non-funny space-tokens.)

In case of the first token of the (remaining) <arbitrary token-sequence> being a digit-token, it needs to be attached to the current digit sequence in argument 3 before calling the loop again with that token removed from the (remaining) <arbitrary token-sequence>.

Of course you also need routines for checking

• whether an argument is empty.
• whether an argument's first token is an opening brace.
• whether an argument's first token is a space token.
• whether an argument's first token is a digit-token.

\UD@ExtractKthDigitSequence{<number K>}{<arbitrary token sequence>} and \UD@ExtractKthDigitSequenceFromJobname{<number K>} "feed" the result of carrying out that loop to another macro which is called \UD@ExtractKthArg{<integer K>}{<list of undelimited args>} which in turn is a routine for delivering the K-th undelimited argument from a list of undelimited/brace-nested arguments.

Everything is implemented so that it will also work in expansion-contexts like \csname..\endcsname.

Neither do you need extensions like eTeX or LuaTeX, nor do you need any additional LaTeX2e packages like expl3 or substr or the like.

\documentclass{article}
\makeatletter
%%=============================================================================
%% Paraphernalia
%%.............................................................................
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@Exchange[2]{#2#1}%
\newcommand\UD@gobblespace{}\UD@firstoftwo{\def\UD@gobblespace}{} {}%
%%=============================================================================
%% Check whether argument is empty:
%%-----------------------------------------------------------------------------
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% Due to \romannumeral-expansion the result is delivered after two
%% expansion-steps.
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%%
%% Crank out the cases of \string "hitting"
%% - an opening-brace -> argument is not empty
%% - a non-brace-token -> argument is not empty
%% - a closing-brace -> argument is empty
%%.............................................................................
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
\UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
\UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%=============================================================================
%% Check whether argument's first token is a catcode-1-character
%%-----------------------------------------------------------------------------
%% \UD@CheckWhetherBrace{<Argument which is to be checked>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has leading
%%                        catcode-1-token>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has no leading
%%                        catcode-1-token>}%
%%
%% Due to \romannumeral-expansion the result is delivered after two
%% expansion-steps.
%%
%% Basically this is a variation of \UD@CheckWhetherNull where non-emptiness
%% is ensured so that you need to only crank out the cases of \string "hitting"
%% an opening-brace or a non-brace-token.
%%.............................................................................
\newcommand\UD@CheckWhetherBrace[1]{%
\romannumeral0\expandafter\UD@secondoftwo\expandafter{\expandafter{%
\string#1.}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
\UD@firstoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}%
}%
%%=============================================================================
%% Check whether brace-balanced argument starts with a space-token
%%-----------------------------------------------------------------------------
%% \UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
%%                             {<Tokens to be delivered in case <argument
%%                               which is to be checked>'s 1st token is a
%%                               space-token>}%
%%                             {<Tokens to be delivered in case <argument
%%                               which is to be checked>'s 1st token is not
%%                               a space-token>}%
%%
%% Due to \romannumeral-expansion the result is delivered after two
%% expansion-steps.
%%.............................................................................
\romannumeral0\UD@CheckWhetherNull{#1}%
{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}%
}%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@secondoftwo#1{}}%
{\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
{\UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter}\expandafter\expandafter
\expandafter}\expandafter\UD@secondoftwo\expandafter{\string}%
}%
%%=============================================================================
%% Check whether argument does not contain "!" (unless nested in braces):
%%-----------------------------------------------------------------------------
%% \UD@CheckWhetherNoExclam{<Argument which is to be checked>}%
%%                         {<Tokens to be delivered in case <argument which is
%%                           to be checked> does not contain !>}%
%%                         {<Tokens to be delivered in case <argument which is
%%                           to be checked> does contain !>
%%.............................................................................
\newcommand\UD@GobbleToExclam{}%
\long\def\UD@GobbleToExclam#1!{}%
\newcommand\UD@CheckWhetherNoExclam[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToExclam#1!}%
}%
%%=============================================================================
%% Check whether argument is a single explicit character-token of
%% category code 12 (other) that denotes digit:
%%-----------------------------------------------------------------------------
%% \UD@CheckWhetherdigit{<Argument which is to be checked>}%
%%                      {<Tokens to be delivered in case <argument which is
%%                        to be checked> is a single catcode-12-digit>}%
%%                      {<Tokens to be delivered in case <argument which is
%%                        to be checked> is not a single catcode-12-digit>
%%
%% Due to \romannumeral-expansion the result is delivered after two
%% expansion-steps.
%%.............................................................................
\newcommand\UD@CheckWhetherdigitfork{}%
\long\def\UD@CheckWhetherdigitfork#1!0!1!2!3!4!5!6!7!8!9!#2#3!!!!{#2}%
\newcommand\UD@CheckWhetherdigit[1]{%
\romannumeral0%
\UD@CheckWhetherNoExclam{#1}{%
\UD@CheckWhetherdigitfork
!#1!1!2!3!4!5!6!7!8!9!{\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
!0!#1!2!3!4!5!6!7!8!9!{\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
!0!1!#1!3!4!5!6!7!8!9!{\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
!0!1!2!#1!4!5!6!7!8!9!{\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
!0!1!2!3!#1!5!6!7!8!9!{\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
!0!1!2!3!4!#1!6!7!8!9!{\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
!0!1!2!3!4!5!#1!7!8!9!{\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
!0!1!2!3!4!5!6!#1!8!9!{\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
!0!1!2!3!4!5!6!7!#1!9!{\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
!0!1!2!3!4!5!6!7!8!#1!{\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
!0!1!2!3!4!5!6!7!8!9!{\UD@firstoftwo\expandafter{} \UD@secondoftwo}%
!!!!%
}{\UD@firstoftwo\expandafter{} \UD@secondoftwo}%
}%
%%=============================================================================
%% Extract K-th inner undelimited argument:
%%-----------------------------------------------------------------------------
%% \UD@ExtractKthArg{<integer K>}{<list of undelimited args>}
%%
%% In case there is no K-th argument in <list of indelimited args> :
%%   Does not deliver any token.
%% In case there is a K-th argument in <list of indelimited args> :
%%   Does deliver that K-th argument with one level of braces removed.
%%
%% Examples:
%%
%%   \UD@ExtractKthArg{0}{ABCDE} yields: <nothing>
%%
%%   \UD@ExtractKthArg{3}{ABCDE} yields:  C
%%
%%   \UD@ExtractKthArg{3}{AB{CD}E} yields:  CD
%%
%%   \UD@ExtractKthArg{4}{{001}{002}{003}{004}{005}} yields: 004
%%
%%   \UD@ExtractKthArg{6}{{001}{002}{003}} yields: <nothing>
%%
%%
%% Due to \romannumeral-expansion the result is delivered after two
%% expansion-steps.
%%.............................................................................
\newcommand\UD@ExtractKthArg[1]{%
\romannumeral0%
% #1: <integer number K>
\expandafter\UD@ExtractKthArgCheck
\expandafter{\romannumeral\number\number#1 000}%
}%
\newcommand\UD@ExtractKthArgCheck[2]{%
\UD@CheckWhetherNull{#1}{ }{%
\expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}#1}{#2}%
}%
}%
\newcommand\UD@ExtractKthArgLoop[2]{%
\UD@CheckWhetherNull{#2}{ }{%
\UD@CheckWhetherNull{#1}{%
\UD@ExtractFirstArgLoop{#2\UD@SelDOm}%
}{%
\expandafter\UD@Exchange\expandafter{\expandafter{\UD@firstoftwo{}#2}}%
{\expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}#1}}%
}%
}%
}%
\newcommand\UD@RemoveTillUD@SelDOm{}%
\long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
{\UD@firstoftwo{\expandafter}{} \UD@secondoftwo{}#1}%
{\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%
%%=============================================================================
%% \UD@ExtractDigitSequences{<token sequence>}
%%-----------------------------------------------------------------------------
%% Extracts sequences of explicit character tokens of category code 12
%% that denote digits from <token sequence>, nests each such sequence
%% into curly braces:
%%
%% E.g., \UD@ExtractDigitSequences{00foo78Bar66}
%% yields: {00}{78}{66}%
%%
%% E.g., \UD@ExtractDigitSequences{00foo78Bar66Baz543BaT954}
%% yields: {00}{78}{66}{543}{954}%
%%
%% Does not deliver any token in case <token sequence> does not contain
%% explicit character-tokens of category code 12(other) that denote
%% digits.
%%
%% Due to \romannumeral-expansion the result is delivered after two
%% expansion-steps.
%%.............................................................................
\newcommand\UD@ExtractDigitSequences[1]{%
\romannumeral0\UD@extractDigitSequencesLoop{#1}{}{}%
}%
\newcommand\UD@extractDigitSequencesLoop[3]{%
\UD@CheckWhetherNull{#1}{%
\UD@CheckWhetherNull{#3}{ #2}{ #2{#3}}%
}{%
\UD@CheckWhetherBrace{#1}{%
\expandafter\UD@Exchange\expandafter{%
\expandafter{\romannumeral0%
\UD@CheckWhetherNull{#3}{\UD@Exchange{{#2}}}{\UD@Exchange{{#2{#3}}}}%
{\expandafter\UD@extractDigitSequencesLoop
\expandafter{\romannumeral0\UD@ExtractKthArgCheck{m}{#1}}%
}{}%
}%
}%
{\expandafter\UD@extractDigitSequencesLoop\expandafter{\UD@firstoftwo{}#1}}%
{}%
}{%
\UD@CheckWhetherNull{#3}{\UD@Exchange{{#2}}}{\UD@Exchange{{#2{#3}}}}%
{\expandafter\UD@extractDigitSequencesLoop\expandafter{\UD@gobblespace#1}}%
{}%
}{%
\expandafter\UD@CheckWhetherdigit
\expandafter{\romannumeral0\UD@ExtractKthArgCheck{m}{#1}}{%
\expandafter\expandafter\expandafter\UD@Exchange
\expandafter\expandafter\expandafter{%
\expandafter\expandafter\expandafter{%
\expandafter\UD@Exchange
\expandafter{\romannumeral0\UD@ExtractKthArgCheck{m}{#1}}{#3}%
}%
}%
{\expandafter\UD@extractDigitSequencesLoop\expandafter{\UD@firstoftwo{}#1}{#2}}%
}{%
\UD@CheckWhetherNull{#3}{\UD@Exchange{{#2}}}{\UD@Exchange{{#2{#3}}}}%
{\expandafter\UD@extractDigitSequencesLoop\expandafter{\UD@firstoftwo{}#1}}%
{}%
}%
}%
}%
}%
}%
%%=============================================================================
%% \UD@ExtractKthDigitSequence{<integer K>}{<token sequence>}
%%-----------------------------------------------------------------------------
%% Extracts the K-th sequence of explicit character-tokens of category
%% code 12 (other) that denote digits from <token sequence> if existent.
%% Otherwise doesn't deliver any token.
%%
%% Due to \romannumeral-expansion the result is delivered after two
%% expansion-steps.
%%.............................................................................
\newcommand\UD@ExtractKthDigitSequence[2]{%
\romannumeral0%
\expandafter\UD@Exchange\expandafter{%
\expandafter{\romannumeral0\UD@extractDigitSequencesLoop{#2}{}{}}%
}{%
\expandafter\UD@ExtractKthArgCheck
\expandafter{\romannumeral\number\number#1 000}%
}%
}%
%%=============================================================================
%% \UD@ExtractDigitSequencesFromJobname
%%-----------------------------------------------------------------------------
%% Extracts sequences of explicit character tokens of category code 12
%% that denote digits from the top-level-expansion of the control-word-
%% token \jobname, nests each such sequence into curly braces:
%%
%% E.g., if \jobname = 00foo78Bar66, then
%%
%%    \UD@ExtractDigitSequencesFromJobname
%%
%% yields: {00}{78}{66}%
%%
%% E.g., if \jobname = 00foo78Bar66Baz543BaT954, then
%%
%%    \UD@ExtractDigitSequencesFromJobname
%%
%% yields: {00}{78}{66}{543}{954}%
%%
%% Does not deliver any token in case <token sequence> does not contain
%% explicit character-tokens of category code 12(other) that denote
%% digits.
%%
%% Due to \romannumeral-expansion the result is delivered after two
%% expansion-steps.
%%.............................................................................
\newcommand\UD@ExtractDigitSequencesFromJobname{%
\romannumeral0%
\expandafter\UD@extractDigitSequencesLoop\expandafter{\jobname}{}{}%
}%
%%=============================================================================
%% \UD@ExtractKthDigitSequenceFromJobname{<integer K>}
%%-----------------------------------------------------------------------------
%% Extracts the K-th sequence of explicit character-tokens of category
%% code 12 (other) that denote digits from the top-level-expansion of the
%% control-word-token \jobname if existent.
%% Otherwise doesn't deliver any token.
%%
%% Due to \romannumeral-expansion the result is delivered after two
%% expansion-steps.
%%.............................................................................
\newcommand\UD@ExtractKthDigitSequenceFromJobname[1]{%
\romannumeral
\expandafter\UD@Exchange\expandafter{\expandafter{\jobname}}%
{\expandafter\UD@secondoftwo\UD@ExtractKthDigitSequence{#1}}%
}%
\makeatother

\begin{document}

\makeatletter

\def\braceshowloop#1{%
\ifx\relax#1\expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi
{}{\{#1\}\braceshowloop}%
}%

\noindent
\verb|\UD@ExtractDigitSequences{{{32}54{}t 65zk_+} 8}|:
\expandafter\expandafter\expandafter\braceshowloop
\UD@ExtractDigitSequences{{{32}54{}t 65zk_+} 8}\relax\\
\verb|\UD@ExtractKthDigitSequence{-1}{{{32}54{}t 65zk_+} 8}|:
\UD@ExtractKthDigitSequence{-1}{{{32}54{}t 65zk_+} 8}\\
\verb|\UD@ExtractKthDigitSequence{0}{{{32}54{}t 65zk_+} 8}|:
\UD@ExtractKthDigitSequence{0}{{{32}54{}t 65zk_+} 8}\\
\verb|\UD@ExtractKthDigitSequence{1}{{{32}54{}t 65zk_+} 8}|:
\UD@ExtractKthDigitSequence{1}{{{32}54{}t 65zk_+} 8}\\
\verb|\UD@ExtractKthDigitSequence{2}{{{32}54{}t 65zk_+} 8}|:
\UD@ExtractKthDigitSequence{2}{{{32}54{}t 65zk_+} 8}\\
\verb|\UD@ExtractKthDigitSequence{3}{{{32}54{}t 65zk_+} 8}|:
\UD@ExtractKthDigitSequence{3}{{{32}54{}t 65zk_+} 8}\\
\verb|\UD@ExtractKthDigitSequence{4}{{{32}54{}t 65zk_+} 8}|:
\UD@ExtractKthDigitSequence{4}{{{32}54{}t 65zk_+} 8}\\
\verb|\UD@ExtractKthDigitSequence{5}{{{32}54{}t 65zk_+} 8}|:
\UD@ExtractKthDigitSequence{5}{{{32}54{}t 65zk_+} 8}\\
\verb|\jobname|:
\jobname\\
\verb|\UD@ExtractDigitSequencesFromJobname|:
\expandafter\expandafter\expandafter\braceshowloop
\UD@ExtractDigitSequencesFromJobname\relax\\
\verb|\UD@ExtractKthDigitSequenceFromJobname{-1}|:
\UD@ExtractKthDigitSequenceFromJobname{-1}\\
\verb|\UD@ExtractKthDigitSequenceFromJobname{0}|:
\UD@ExtractKthDigitSequenceFromJobname{0}\\
\verb|\UD@ExtractKthDigitSequenceFromJobname{1}|:
\UD@ExtractKthDigitSequenceFromJobname{1}\\
\verb|\UD@ExtractKthDigitSequenceFromJobname{2}|:
\UD@ExtractKthDigitSequenceFromJobname{2}\\
\verb|\UD@ExtractKthDigitSequenceFromJobname{3}|:
\UD@ExtractKthDigitSequenceFromJobname{3}\\
\verb|\UD@ExtractKthDigitSequenceFromJobname{4}|:
\UD@ExtractKthDigitSequenceFromJobname{4}\\
\verb|\UD@ExtractKthDigitSequenceFromJobname{5}|:
\UD@ExtractKthDigitSequenceFromJobname{5}\\
\verb|\UD@ExtractKthDigitSequenceFromJobname{6}|:
\UD@ExtractKthDigitSequenceFromJobname{6}\\

\end{document}