Here's an expandable version of \BeforeSubString which I (with all my creativity) called \ExpBeforeSubString:
\documentclass{article}
\makeatletter
\def\ExpBeforeSubString#1#2{%
\expandafter\befsub@detoki\expandafter{\detokenize{#2}}{#1}}
\def\befsub@detoki#1#2{%
\expandafter\befsub@detokii\expandafter{\detokenize{#2}}{#1}}
\def\befsub@detokii#1#2{%
\rn@ifsinglechar{#1}%
{\befsub@loop{}{#1}#2\q@rec@tail\q@rec@stop}%
{\errmessage{`#1' should be a single, non-empty token.}}}
\def\q@rec@tail{\q@rec@tail}
\def\befsub@loop#1#2#3{%
\befsub@iftail{#3}%
{\befsub@return{#1}}%
{%
\befsub@match{#2}{#3}%
{\befsub@return{#1}}%
{\befsub@loop{#1#3}{#2}}%
}%
}
\def\befsub@match#1#2{%
\if#1#2%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\def\befsub@return#1#2\q@rec@stop{#1}
\def\befsub@iftail#1{%
\ifx\q@rec@tail#1%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\edef\rn@catofamp{\the\catcode`\&}
\catcode`\&=11
\long\def\rn@gobble#1&{%
\romannumeral-`0\rn@@gobble#1\rn@qrtail &}
\long\def\rn@@gobble#1#2&{%
\ifx\rn@qrtail#1%
\expandafter\rn@@gobble@end
\else
\expandafter\rn@de@tail
\fi#2}
\def\rn@@gobble@end{ }
\long\def\rn@de@tail#1\rn@qrtail{ #1}
\long\def\rn@ifsinglechar#1{%
\rn@ifempty{#1}%
{\@secondoftwo}%
{%
\if\relax\expandafter\rn@gobble\detokenize{#1}&\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}%
}
\catcode`\&=\rn@catofamp
\long\def\rn@ifempty#1{%
\if\relax\detokenize{#1}\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\makeatother
\begin{document}
\newcommand{\abc}{yay}
\csname \ExpBeforeSubString{|}{abc|def}\endcsname
\end{document}
Now using
\newcommand{\abc}{yay}
\csname \ExpBeforeSubString{|}{abc|def}\endcsname
yields yay. Yay!
Compare the length of code with the original (non expandable) version:
\makeatletter
\newcommand*\BeforeSubString[2]{%
\su@ExpandTwoArgs{#1}{#2}\su@BeforeSubString
}
\newcommand*\su@BeforeSubString[2]{%
\def\su@rest##1#1##2\@nil{##1}%
\IfSubStringInString{#1}{#2}{\su@rest#2\@nil}{#2}%
}
\newcommand\su@ExpandTwoArgs[3]{%
\protected@edef\su@SubString{#1}%
\protected@edef\su@String{#2}%
\expandafter\expandafter\expandafter#3%
\expandafter\expandafter\expandafter{%
\expandafter\su@SubString\expandafter
}\expandafter{\su@String}%
}
\newcommand*\IfSubStringInString[2]{%
\su@ExpandTwoArgs{#1}{#2}\su@IfSubStringInString
}
\newcommand*\su@IfSubStringInString[2]{%
\def\su@compare##1#1##2\@nil{%
\def\su@param{##2}%
\ifx\su@param\@empty
\expandafter\@secondoftwo
\else
\expandafter\@firstoftwo
\fi
}%
\su@compare#2\@nnil#1\@nil
}
\makeatother
Or a version with xstring which allows you to store the match in a temporary macro:
\documentclass{article}
\usepackage{xstring}
\begin{document}
\newcommand{\abc}{yay}
\StrBefore{abc|def}{|}[\tempmacro]
\csname\tempmacro\endcsname
\end{document}
\BeforeSubStringis not expandable, so it won't work there. Do you need to use\BeforeSubStringor some other command/package will do? – Phelype Oleinik Jun 27 '19 at 01:33\abctoyay), but some operations are not expandable, which means that they need to be processed in a deeper level by TeX. See the second part of this answer for a brief description of that. If you want to read more, then see this thread too. – Phelype Oleinik Jun 27 '19 at 01:38\csname...\endcsnamerequires that everything inside it be expandable. And while it is possible to make many useful macros expandable (for example,expl3contains an expandable floating point unit!), the code is usually much more complex than an unexpandable code. For an example of this extra complication, compare the code in this question with the same code in my answer to see the difference in the amount of code. – Phelype Oleinik Jun 27 '19 at 01:44