1

I'm fairly new to LaTeX, and want to know if I have a string John Citizen how can I break down so that I can access John and Citizen independently of each other through out the document.

Currently my approach is:

\newcommand{\FirstName}{John}
\newcommand{\LastName}{Citizen}
\newcommand{\FullName}{\FirstName{} \LastName{}}

Q: I would like to derive \FirstName and \LastName from \FullName - How can I do this?

5
  • 2
    How flexible should this first name/last name detection work? How would names like "Wolfgang Amadeus Beethoven" or "Ludwig van Mozart" be handled?
    – siracusa
    Jul 24, 2019 at 4:56
  • 1
    And how should names with a “Junior” component, such as “Robert E. Lucas, Jr.” or “Publius Cornelius Scipio Africanus Maior”, be treated?
    – Mico
    Jul 24, 2019 at 5:31
  • First and last name should be enough .... just two substrings.
    – 3kstc
    Jul 24, 2019 at 6:27
  • You can use the xstring package to extract substrings separate by a space. Jul 24, 2019 at 17:22
  • @JohnKormylo Are you able to share how one would do this in the answers please?
    – 3kstc
    Jul 25, 2019 at 0:49

4 Answers 4

1

I could just say RTFM, but the latest version of the manual is unreadable.

\documentclass{article}
\usepackage{xstring}
\begin{document}
\edef\fullname{Jane Doe}%
\StrBefore{\fullname}{ }[\firstname]%
\StrBehind{\fullname}{ }[\lastname]%
{\fullname} or \lastname, \firstname
\end{document} 
2
  • I did go through manual - it's just a terrible manual - that's why I asked - sorry :) Thank you for your answer!
    – 3kstc
    Jul 26, 2019 at 6:16
  • You could read it? With Adobe Acrobat 9 it is just a jumble of overlapping letters. Jul 26, 2019 at 14:55
4

Here is another solution using expl3 (different from siracusa's solution). It provides three macros \kstcsplitname, \kstcsplitnameoneexp and \kstcsplitnamefullexp, all based on the same macro \kstc_split_name:nNN in order to handle typical use cases you might be confronted to:

  • \kstcsplitname splits its first argument without doing any expansion on it;

  • \kstcsplitnameoneexp performs one expansion step on its first argument, then splits the result;

  • \kstcsplitnamefullexp performs full expansion on its first argument, then splits the result.

Look at the examples below, I'm sure you'll understand the differences between these three situations. In all cases, the second and third arguments are macro names you have to provide; they indicate where the first name and last name will be stored once the splitting operation has been done.

You may want to modify the strings -first~name~missing- and -last~name~missing- in the base function \kstc_split_name:nNN, so as to reflect the desired output when at least one of the two names is missing.

Note:

  • The ~ character is a space under \ExplSyntaxOn regime.

  • It would also be possible to trigger an error message when one or both names are missing.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\seq_new:N \l__kstc_tmpa_seq

\cs_new_protected:Npn \kstc_split_name:nNN #1#2#3
  {
    \tl_clear_new:N #2
    \tl_clear_new:N #3
    % ~ is a space under \ExplSyntaxOn regime; it is the separator here
    \seq_set_split:Nnn \l__kstc_tmpa_seq {~} {#1}
    \seq_pop_left:NN \l__kstc_tmpa_seq #2
    \seq_pop_left:NN \l__kstc_tmpa_seq #3

    \tl_if_blank:VT #2 { \tl_set:Nn #2 { -first~name~missing- } }
    \bool_if:nT { \tl_if_eq_p:NN #3 \q_no_value || \tl_if_blank_p:V #3 }
      { \tl_set:Nn #3 { -last~name~missing- } }
  }

\cs_generate_variant:Nn \kstc_split_name:nNN { o, x }

\NewDocumentCommand \kstcsplitname { m m m }
  {
    \kstc_split_name:nNN {#1} #2 #3
  }

% Perform one expansion step on the first argument before passing the result
% to \kstc_split_name:nNN.
\NewDocumentCommand \kstcsplitnameoneexp { m m m }
  {
    \kstc_split_name:oNN {#1} #2 #3
  }

% Perform full expansion on the first argument before passing the result to
% \kstc_split_name:nNN.
\NewDocumentCommand \kstcsplitnamefullexp { m m m }
  {
    \kstc_split_name:xNN {#1} #2 #3
  }

\ExplSyntaxOff

\begin{document}

\section*{No expansion of the first argument}

\kstcsplitname{John Citizen}{\firstname}{\lastname}%
%
First: '\firstname'. Last: '\lastname'.

\section*{One expansion step on the first argument}

\newcommand*{\fullname}{Jane Doe}%
%
\kstcsplitnameoneexp{\fullname}{\firstname}{\lastname}%
First: '\firstname'. Last: '\lastname'.

\section*{Full expansion of the first argument}

\newcommand*{\anindirect}{\fullnamedefin}%
\newcommand*{\fullnamedefin}{\ition ll}%
\newcommand*{\ition}{Jack Du}%
%
\kstcsplitnamefullexp{\anindirect}{\firstname}{\lastname}%
First: '\firstname'. Last: '\lastname'.

\section*{First argument contains only one name}

\kstcsplitname{June}{\firstname}{\lastname}%
%
First: '\firstname'. Last: '\lastname'.

\section*{First argument is blank (empty or not)}

\kstcsplitname{}{\firstname}{\lastname}% first arg empty
%
First: '\firstname'. Last: '\lastname'.

\noindent
\kstcsplitname{ }{\firstname}{\lastname}% first arg non-empty, yet blank
%
First: '\firstname'. Last: '\lastname'.

\end{document}

Screenshot

3

Using the expl3 package, the splitting can be quite easily achieved by using the \seq_set_split:Nnn function. The first parameter of this function is the target sequence where the individual elements are stored, the second parameter is the delimiter to split at (we have to use ~ instead of a space character here, because in expl3 syntax mode bare spaces are ignored), and the last parameter is the text to be split.

After splitting we set \FirstName and \LastName empty, and then fill them again, depending on how many elements are present after splitting the input: for one set only the first name, for two set first and last name, for three the former two are treated as the first name and the latter one is treated as the last name.

If you are not familiar with the expl3 syntax, the code may be a bit hard to read, but the implementation is actually quite straight-forward.

\documentclass{article}
\usepackage{expl3}

\ExplSyntaxOn
\newcommand\FullName[1]{%
    \seq_set_split:Nnn \l_tmpa_seq { ~ } { #1 }

    \cs_gset:Npx \FirstName { }
    \cs_gset:Npx \LastName { }
    \int_case:nn { \seq_count:N \l_tmpa_seq } {
        { 1 } {
            \cs_gset:Npx \FirstName { \seq_item:Nn \l_tmpa_seq { 1 } }
        }
        { 2 } {
            \cs_gset:Npx \FirstName { \seq_item:Nn \l_tmpa_seq { 1 } }
            \cs_gset:Npx \LastName { \seq_item:Nn \l_tmpa_seq { 2 } }
        }
        { 3 } {
            \cs_gset:Npx \FirstName { \seq_item:Nn \l_tmpa_seq { 1 } ~
                                      \seq_item:Nn \l_tmpa_seq { 2 } }
            \cs_gset:Npx \LastName { \seq_item:Nn \l_tmpa_seq { 3 } }
        }
    }
}
\ExplSyntaxOff

\begin{document}
\FullName{}
First: ``\FirstName'', Last: ``\LastName''\par
\FullName{John}
First: ``\FirstName'', Last: ``\LastName''\par
\FullName{John Citizen}
First: ``\FirstName'', Last: ``\LastName''\par
\FullName{John K. Citizen}
First: ``\FirstName'', Last: ``\LastName''\par
\end{document}

outputs

enter image description here

2

Here's a LuaLaTeX-based solution. The code below provides two LaTeX macros called \firstname and \lastname, which are wrappers for underlying Lua functions called extract_first and extract_last, respectively.

The solution assumes (a) that a "full name" consists of exactly two parts -- the first and last names, respectively and (b) that the two parts are separated either by one or more whitespace characters or by exactly one other non-letter character (such as "/"). Note that the input of both LaTeX macros can be any material that expands to a string that contains (at least) one interior non-letter character.

enter image description here

\documentclass{article}
\usepackage{luacode} % for 'luacode' env. and '\luastring' macro
\begin{luacode}
function extract_first ( s )
  aa = s:find( "%A" ) -- locate the first non-letter char.
  tex.sprint ( s:sub(1,aa-1) )
end
function extract_last ( s )
  aa = s:find( "%A" )
  tex.sprint ( s:sub(aa+1) )
end
\end{luacode}

\newcommand{\firstname}[1]{\directlua{extract_first(\luastring{#1})}}
\newcommand{\lastname}[1]{\directlua{extract_last(\luastring{#1})}}

\begin{document}
\def\fullnameA{Mark   Twain}
\def\fullnameB{Ludwig/van   Beethoven} % "/" is the first non-letter character
\firstname{\fullnameA}.\lastname{\fullnameB}.
\end{document} 
2
  • My sincere congratulationssssssssssssssss. 300kkkkkkkkkkkkkkkkkkkkkkkk. My sincere estimate :-) best wishes.
    – Sebastiano
    Aug 2, 2019 at 18:45
  • 1
    @Sebastiano - Mille, millione grazie!!!
    – Mico
    Aug 2, 2019 at 18:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.