我对 LaTeX 还很陌生,想知道如果我有一个字符串,John Citizen
我该如何分解它,以便我可以在整个文档中独立地访问它们John
。Citizen
目前我的做法是:
\newcommand{\FirstName}{John}
\newcommand{\LastName}{Citizen}
\newcommand{\FullName}{\FirstName{} \LastName{}}
问:我想要导出和\FirstName
-我该怎么做?\LastName
\FullName
答案1
我只能说“RTFM”,但最新版本的手册难以阅读。
\documentclass{article}
\usepackage{xstring}
\begin{document}
\edef\fullname{Jane Doe}%
\StrBefore{\fullname}{ }[\firstname]%
\StrBehind{\fullname}{ }[\lastname]%
{\fullname} or \lastname, \firstname
\end{document}
答案2
这是另一个使用的解决方案expl3
(不同于 siracusa 的解决方案)。它提供了三个宏\kstcsplitname
,\kstcsplitnameoneexp
和\kstcsplitnamefullexp
,它们都基于同一个宏,\kstc_split_name:nNN
以便处理您可能遇到的典型用例:
\kstcsplitname
拆分其第一个参数而不对其进行任何扩展;\kstcsplitnameoneexp
对其第一个参数执行一个扩展步骤,然后分割结果;\kstcsplitnamefullexp
对其第一个参数执行完全扩展,然后分割结果。
看看下面的例子,我相信你会明白这三种情况的区别。在所有情况下,第二个和第三个参数都是你必须提供的宏名称;它们表示在完成拆分操作后名字和姓氏将存储在何处。
您可能需要修改基本函数中的字符串-first~name~missing-
和,以便在两个名称中至少一个缺失时反映所需的输出。-last~name~missing-
\kstc_split_name:nNN
笔记:
性格
~
是政权统治下的空间\ExplSyntaxOn
。当其中一个或两个名字缺失时,也可能会触发错误消息。
\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}
答案3
使用该expl3
包,可以通过使用函数轻松实现拆分\seq_set_split:Nnn
。该函数的第一个参数是存储各个元素的目标序列,第二个参数是要拆分的分隔符(我们必须~
在这里使用空格字符,因为在expl3
语法模式下,空格会被忽略),最后一个参数是要拆分的文本。
拆分后,我们设置\FirstName
并\LastName
清空它们,然后再次填充,具体取决于拆分输入后有多少个元素:对于一组,只有名字;对于两组,有名字和姓氏;对于三组,前两个被视为名字,后者被视为姓氏。
如果您不熟悉expl3
语法,代码可能有点难以阅读,但实现实际上非常简单。
\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}
输出
答案4
这是一个基于 LuaLaTeX 的解决方案。下面的代码提供了两个名为\firstname
和的 LaTeX 宏,它们分别是名为和 的\lastname
底层 Lua 函数的包装器。extract_first
extract_last
该解决方案假设 (a) “全名”恰好由两部分组成 - 分别是名字和姓氏,以及 (b) 这两部分由一个或多个空格字符或恰好一个其他非字母字符(例如“/”)分隔。请注意,两个 LaTeX 宏的输入可以是任何扩展为包含(至少)一个内部非字母字符的字符串的材料。
\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}