# How to match last substring

I am working on displaying source code for which I pass a path to a macro. Now I am wondering if it is possible using xstring or stringstrings to match from after the last delimiter, i.e. / to the end of the string to determine the filename.

Example: I might pass ../code/subfolder/project/code.java to the macro for which I want to extract the substring code.java. It seems easy to match the first occurrence of a character, but not the last.

No package is needed for that, you can use LaTeX's filename parser:

\documentclass{article}

\begin{document}

\makeatletter

\filename@parse{../code/subfolder/project/code.java}

[\filename@area]

[\filename@base]

[\filename@ext]

\end{document}

• Accepted because it is the simplest answer (and most highly voted), but in all honesty all answers given are of equal high quality. Each answer has its own advantages/disadvantages. May 19 '15 at 22:36

Here is a method with xstring:

\documentclass{article}
\usepackage{xstring}
\newcommand*\filename[1]{%
\IfSubStr{#1}/
{\StrCount{#1}/[\ossepoccur]%
\StrBehind[\ossepoccur]{#1}/\relax
}
{#1}%
}
\begin{document}
\filename{abc.foo}

\filename{../code/subfolder/project/code.java}
\end{document}


Here's a generic extractor of the last item in a delimited string:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\extractlast}{O{/}mo}
{
\seq_set_split:Nnn \l_stroobants_string_seq { #1 } { #2 }
\IfNoValueTF { #3 }
{
\seq_item:Nn \l_stroobants_string_seq { -1 }
}
{
\tl_set:Nx #3 { \seq_item:Nn \l_stroobants_string_seq { -1 } }
}
}
\seq_new:N \l_stroobants_string_seq
\ExplSyntaxOff

\begin{document}

\extractlast{../code/subfolder/project/code.java}

\extractlast[-]{a-b-c-def}[\test]

\texttt{\meaning\test}

\end{document}


The first optional argument is the delimiter, default /; the trailing optional argument is a macro name where the last item is stored, if not present, the item is printed.

A fully expandable version, but with a fixed delimiter; you're better not input an empty string, although a test for this can be easily added.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\extractlast}{m}
{
\stroobants_extractlast:nn #1 / \q_nil / \q_nil /
}
\cs_new:Npn \stroobants_extractlast:nn #1 / #2 / \q_nil /
{
\str_if_eq:nnTF { #2 } { \q_nil }
{% end of recursion
#1
}
{% go on
\stroobants_extractlast:nn #2 / \q_nil /
}
}
\ExplSyntaxOff

\begin{document}
\extractlast{../code/subfolder/project/code.java}

\edef\test{\extractlast{../code/subfolder/project/code.java}}
\texttt{\meaning\test}
\end{document}


Here is a way with stringstrings.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{stringstrings}
\def\fname#1{%
\findchars[q]{#1}{/}%
\edef\tmp{\theresult}%
\convertchar[e]{x#1}{/}{ }%
\getaword[q]{\thestring\ }{\numexpr\tmp+1\relax}%
\edef\thefname{\thestring}%
}
\begin{document}
\fname{../code/subfolder/project/code.java}
The file is \thefname.
\end{document}