如何将字符串变量拆分为数组并从数组中调用

如何将字符串变量拆分为数组并从数组中调用

我对 LaTeX 还很陌生,想知道如果我有一个字符串,John Citizen我该如何分解它,以便我可以在整个文档中独立地访问它们JohnCitizen

目前我的做法是:

\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_firstextract_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} 

相关内容