提取字符串中的第一个单词

提取字符串中的第一个单词

标题几乎说明了一切,我需要一个命令来获取字符串中的第一个单词。

基于这是我另一个问题的答案,我尝试了这个:

\documentclass{article}

\makeatletter
\newcommand\FirstWord[1]{\@firstword#1 \@nil}%
\newcommand\@firstword{}%
\def\@firstword#1 #2\@nil{#1\unskip}%
\makeatother

\begin{document}
    \FirstWord{John, Paul, George and Ringo}
\end{document}

它几乎可以正常工作,除了它包含逗号之外。我得到:

约翰,

而我想要的只是:

约翰

那么我该怎么做呢?

PS:理想情况下,如果括号内有多个单词,则应将它们算作一个。因此\FirstWord{{John, Paul}, George and Ringo}应打印“John, Paul”。

答案1

你已经快完成了,只需删除末尾的逗号即可

\documentclass{article}

\makeatletter
\newcommand\FirstWord[1]{\@firstword#1 \@nil}%
\newcommand\@firstword{}%
\newcommand\@removecomma{}%
\def\@firstword#1 #2\@nil{\@removecomma#1,\@nil}%
\def\@removecomma#1,#2\@nil{#1}
\makeatother

\begin{document}

X\FirstWord{John, Paul, George and Ringo}X

X\FirstWord{John}X

X\FirstWord{John and Paul}X

X\FirstWord{{John, Paul}, George and Ringo}X

\end{document}

在此处输入图片描述

您可以添加进一步的测试来删除其他分隔符

\documentclass{article}

\makeatletter
\newcommand\FirstWord[1]{\@firstword#1 \@nil}%
\def\@firstword#1 #2\@nil{\@removecomma#1,\@nil}%
\def\@removecomma#1,#2\@nil{\@removeperiod#1.\@nil}
\def\@removeperiod#1.#2\@nil{\@removesemicolon#1;\@nil}
\def\@removesemicolon#1;#2\@nil{#1}
\makeatother

\begin{document}

X\FirstWord{John; Paul; George; Ringo}X

X\FirstWord{John. Paul. George. Ringo}X

X\FirstWord{John}X

X\FirstWord{John and Paul}X

X\FirstWord{{John. Paul}. George. Ringo}X

\end{document}

如果你不需要可扩展性,你可以使用l3regex

\documentclass{article}
\usepackage{xparse,l3regex}

\ExplSyntaxOn
\NewDocumentCommand{\FirstWord}{m}
 {
  % split the argument at spaces
  \seq_set_split:Nnn \l_tmpa_seq { ~ } { #1 }
  % get the first item
  \tl_set:Nx \l_tmpa_tl { \seq_item:Nn \l_tmpa_seq { 1 } }
  % remove a trailing period, semicolon or comma (\Z matches the end)
  \regex_replace_once:nnN { [.;,]\Z } { } \l_tmpa_tl
  % output the result
  \tl_use:N \l_tmpa_tl
 }
\ExplSyntaxOff

\begin{document}

X\FirstWord{John, Paul, George and Ringo}X

X\FirstWord{John; Paul; George; Ringo}X

X\FirstWord{John. Paul. George. Ringo}X

X\FirstWord{John}X

X\FirstWord{John and Paul}X

X\FirstWord{{John, Paul}, George and Ringo}X

X\FirstWord{{John. Paul}. George. Ringo}X

\end{document}

答案2

不可否认,有点晚了,但这是第二个基于 LuaLaTeX 的解决方案,它概括了先前的答案由@Nasser 撰写。此答案的模式搜索算法满足以下标准:

  • 如果要搜索的字符串开始使用匹配的花括号分隔的子字符串,返回整个子字符串。

  • 否则,第一个单词被返回。在这里,“单词”要么是字母字符的集合——例如“John”或“Nicolò”——要么是连字符对单词——例如“Kröller-Müller”和“Rhys-Davies”。(换句话说,带连字符的单词被视为两个单词,它们恰好由一个 连接-;对带连字符的单词对中第一个单词的唯一限制是它至少包含两个字符。)在完整字符串中,“单词”之前的任何非字母字符都会被自动丢弃。Lua 代码支持 unicode,即单词可能包含非 ASCII 字母字符(例如öüò)。

在此处输入图片描述

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{fontspec}
\usepackage{luacode} % for 'luacode' environment and '\luastring' macro
%% Lua-side code: A Lua function that does most of the work
\begin{luacode}
function fw ( s )
   if string.find ( s , '^%b{}' ) then
      first = string.sub ( string.match ( s , '%b{}' ), 2, -2 )
   else
      first = unicode.utf8.match ( s , '%w+%-?%w+' )
   end
   tex.sprint ( first ) 
end
\end{luacode}
%% TeX-side code: A macro that invokes the Lua function
\newcommand{\FW}[1]{\directlua{fw(\luastring{#1})}}

\begin{document}

\def\lst{{John and Paul} but not George or Ringo}
\FW{\lst}

\def\lst{'{Bay- Day} Hay}
\FW{\lst}

\def\lst{Kröller-Müller and Schwassmann-Wassmann}
\FW{\lst}

\end{document}

相关内容