第二个函数中解析的词段不能与乳胶中的字符串进行比较?

第二个函数中解析的词段不能与乳胶中的字符串进行比较?

我想通过删除最后一段来解析单词(“1. Book1 p3”变为“1. Book1”或“Book2 p4”变为“Book2”)。我使用函数实现了这一点\FirstPart。现在,我想\FirstPart在函数中使用返回\foo参数来进行字符串比较。如果输入参数符合 ifthenelse 测试,它应该返回相应的键(在示例中,如果输入是“1. Book p.2”,则返回应该是“01Category”)。所以我测试了\foo{\FirstPart{1. Book p.2}},但是我总是得到 FALSE 作为返回值。我认为存在类型不匹配,但是我不知道如何解决这个问题。最后我想使用\foo指定(makeindex 包)的排序顺序\index(自定义环境中的一个条目看起来像:\index{\foo{\FirstPart{#1}}@\FirstPart{#1}!#1}。有人能帮帮我吗?

\documentclass{article}

\makeatletter
\newcommand\FirstPart[1]{#1}%
\newcommand\firstwords{}%
\def\firstwords#1 #2 #3\@nil{\if\relax#3\relax
    #1\relax
    \else
    \foo{#1 #2\relax}
    \fi}    
\makeatother

\usepackage{ifthen}
\newcommand{\foo}[1]{%
    \ifthenelse{\equal{#1}{1. Book}}
    {01Category}
     {FALSE}}

\begin{document}
    
    \foo{\FirstPart{1. Book p.2}}\\
    \foo{1. Book}
    
\end{document}

答案1

不太清楚你想要实现什么。也许是这样的?

\documentclass{article}

\ExplSyntaxOn

\NewExpandableDocumentCommand{\firstwordscase}{mmm}
 {
  \ise_firstwordscase:enn { \text_expand:n { #1 } } { #2 } { #3 }
 }

\cs_new:Nn \ise_firstwordscase:nnn
 {
  \__ise_firstwordscase:nnw { #2 } { #3 } #1 \q_stop
 }
\cs_generate_variant:Nn \ise_firstwordscase:nnn { e }

\cs_new:Npn \__ise_firstwordscase:nnw #1 #2 #3 ~ #4 ~ #5 \q_stop
 {
  \str_case:nnF { #3~#4 } { #1 } { #2 }
 }

\ExplSyntaxOff

\newcommand{\test}{1. Book2 p3} % just for testing

\begin{document}

\firstwordscase{1. Book1 p3}{
  {1. Book1}{01Category}
  {1. Book2}{XYZ}
}{FALSE}
    
\firstwordscase{1. Book2 p3}{
  {1. Book1}{01Category}
  {1. Book2}{XYZ}
}{FALSE}
    
\firstwordscase{\test}{
  {1. Book1}{01Category}
  {1. Book2}{XYZ}
}{FALSE}

\firstwordscase{2. Book1 p1}{
  {1. Book1}{01Category}
  {1. Book2}{XYZ}
}{FALSE}
    
\end{document}

你可以有任意多个大小写切换。

在此处输入图片描述

答案2

为了多样化,这里有一个基于 LuaLaTeX 的解决方案。它由两个 LaTeX 实用程序宏组成,称为\FirstPart\foo,它们\directlua分别调用 Lua 函数,你猜对了,FirstPartfoo。观察因为\directlua是可扩展的,\foo{\FirstPart{1. Book p.2}}\foo{1. Book}产生相同的输出。

在此处输入图片描述

\documentclass{article}
\usepackage{luacode}

%% Lua-side code:
\begin{luacode}
function FirstPart ( s )
  n = s:find ( "%s+%S+$" )
  tex.sprint ( s:sub ( 1 , n - 1 ) )
end

function foo ( s )
  if s == "1. Book" then 
    tex.sprint ( "01Category" )
  else 
    tex.sprint ( "FALSE" )
  end
end
\end{luacode}

%% LaTeX-side code:
\newcommand\FirstPart[1]{\directlua{FirstPart("#1")}}
\newcommand\foo[1]{\directlua{foo("#1")}}

\begin{document}
\obeylines % just for this example
\FirstPart{1. Book1 p3}
\FirstPart{Book2 p4}
\foo{\FirstPart{1. Book p.2}}
\foo{1. Book}
\foo{\FirstPart{Book2 p4}}
\end{document}

答案3

\foo可能仅通过扩展方法测试其参数(扩展后)在附加空格后是否足够的命令?1.⟨space⟩Book⟨space⟩

\makeatletter
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@Exchange,
%%    \UD@stopromannumeral, \UD@CheckWhetherNull,
%%    \UD@CheckWhetherLeadingTokens, \UD@internaltokencheckdefiner
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@Exchange[2]{#2#1}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
  \expandafter\UD@stopromannumeral\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's leading tokens form a specific 
%% token-sequence that does not contain explicit character tokens of 
%% category 1 or 2 or 6:
%%.............................................................................
%% \UD@CheckWhetherLeadingTokens{<argument which is to be checked>}%
%%                              {<a <token sequence> without explicit 
%%                                character tokens of category 1 or 2
%%                                or 6>}%
%%                              {<internal token-check-macro>}%
%%                              {<tokens to be delivered in case
%%                                <argument which is to be checked> has
%%                                <token sequence> as leading tokens>}%
%%                              {<tokens to be delivered in case 
%%                                <argument which is to be checked>
%%                                does not have <token sequence> as
%%                                leading tokens>}%
\newcommand\UD@CheckWhetherLeadingTokens[3]{%
  \romannumeral\UD@CheckWhetherNull{#1}%
  {\expandafter\UD@stopromannumeral\UD@secondoftwo}%
  {%
    % Let's nest things into \UD@firstoftwo{...}{} to make sure they are nested in braces
    % and thus do not disturb when the test is carried out within \halign/\valign:
    \expandafter\UD@firstoftwo\expandafter{%
      \expandafter\expandafter\expandafter\UD@stopromannumeral
      \romannumeral
      \expandafter\UD@secondoftwo\string{\expandafter\UD@@CheckWhetherLeadingTokens#3{{}}#1#2}{}}{}%
  }%
}%
\newcommand\UD@@CheckWhetherLeadingTokens[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
  {\expandafter\expandafter\expandafter\UD@stopromannumeral
   \expandafter\expandafter\expandafter}%
  \expandafter\UD@secondoftwo\expandafter{\string}%
}%
%%-----------------------------------------------------------------------------
%% \UD@internaltokencheckdefiner{<internal token-check-macro>}%
%%                              {<token sequence>}%
%% Defines <internal token-check-macro> to snap everything 
%% until reaching <token sequence>-sequence and spit that out
%% nested in braces.
%%-----------------------------------------------------------------------------
\newcommand\UD@internaltokencheckdefiner[2]{%
  \@ifdefinable#1{\long\def#1##1#2{{##1}}}%
}%
\makeatother


\documentclass{article}

\makeatletter
\UD@internaltokencheckdefiner{\GobbleTillFirstBookPhrase}{1. Book }%
\newcommand\foo[1]{%
   \expanded{\noexpand\UD@CheckWhetherLeadingTokens{#1 }}%
                                {1. Book }%
                                {\GobbleTillFirstBookPhrase}%
                                {01Category}%
                                {FALSE}%
}%
\newcommand\FirstPart[1]{#1}%
\makeatother

\begin{document}

\noindent
Test 1: \foo{\FirstPart{1. Book p.2}}\\
Test 2: \foo{\FirstPart{1. Book p.2 some  } more text}\\
Test 3: \foo{1. Book}\\
Test 4: \foo{2. Book p. 2}\\
Test 5: \foo{1. Bookbinding}
    
\end{document}

在此处输入图片描述


我考虑详细阐述一个循环,该循环从参数的右侧连续删除以空格分隔的组件,并迭代执行\ifthenelse-comparison,直到字符串与短语匹配1. Book或不包含空格。

但您提到您希望将其与命令一起使用\index。在许多地方,命令的参数\index需要完全可扩展,而对于如果那么\ifthenelse命令。

答案4

以下内容受到egreg的回答的启发:

\firstwordscase使用其第二个参数执行“文本扩展”,去掉前导和尾随空格标记,然后提取最多与第一个参数所表示的一样多的空格分隔单词。然后使用第三个和第四个参数所表示的结果执行字符串大小写转换。第二个参数中单词之间的多个空格标记合并为一个空格标记。括号组的内容被视为一个单词,其中周围的括号组不会被去掉,空格标记等也不会受到影响。

\ExplSyntaxOn
\errorcontextlines=100000
\cs_new:Npn \UD_ExtractFirstSpaceDelimitedArg:n #1#2 {
  \cs_new:Npn \UD_GobbleKnownFirstSpace:w #2 {}
  \cs_new:Npn \UD_GobbleFirstSpaceDelimitedArg:w ##1#2 {}
  \cs_new:Npn \UD_RemoveSecondSpaceDelimitedArg:ww ##1#2##2#2#1{{##1}#2}
  \cs_new:Npn \UD_RemoveBracesFromSpaceDelimitedArg:w ##1#2{\use_i:nn ##1}
  %%-----------------------------------------------------------------------------
  %% Loop for extracting the first space-delimited argument from list of
  %% space-separated components - the result is returned wrapped in curly braces
  %%.............................................................................
  \cs_gset:Npn \UD_ExtractFirstSpaceDelimitedArg:n ##1 {
    \exp:w \UD_ExtractFirstSpaceDelimitedLoop:n{{}{}##1#2#2#1}
  }
  \cs_new:Npn\UD_ExtractFirstSpaceDelimitedLoop:n ##1 {
    \tl_if_empty:oTF {\UD_GobbleFirstSpaceDelimitedArg:w ##1}
    { \exp_args:Nno \use:n {\exp_args:No\exp_end:}{\UD_RemoveBracesFromSpaceDelimitedArg:w ##1} }
    { \exp_args:No\UD_ExtractFirstSpaceDelimitedLoop:n{\UD_RemoveSecondSpaceDelimitedArg:ww ##1} }
  }
  %%-----------------------------------------------------------------------------
  %% Removal of the first space-delimited argument from list of space-separated
  %% components - the resulting list is returned wrapped in curly braces
  %%.............................................................................
  \cs_new:Npn \UD_RemoveFirstSpaceDelimitedArg:n ##1 {
    \exp:w \tl_if_empty:oTF {\UD_GobbleFirstSpaceDelimitedArg:w ##1#2}
    {\exp_end:{}}{\exp_args:No\exp_end:{\UD_GobbleFirstSpaceDelimitedArg:w ##1}}
  }
  %%-----------------------------------------------------------------------------
  %% Check whether brace-balanced argument starts with an explicit space-token
  %%.............................................................................
  %% \CheckWhetherLeadingExplicitSpace{<Argument which is to be checked>}%
  %%                                  {<Tokens to be delivered in case <argument
  %%                                    which is to be checked> does have a
  %%                                    leading explicit space-token>}%
  %%                                  {<Tokens to be delivered in case <argument
  %%                                    which is to be checked> does not have a
  %%                                    a leading explicit space-token>}%
  \cs_new:Npn \CheckWhetherLeadingExplicitSpace ##1 {
    \exp:w \tl_if_empty:nTF {##1}
    {\exp_after:wN \exp_end: \use_ii:nn}
    { % Let's nest things into \use_i:nn{...}{} to make sure they are nested in braces
      % and thus do not disturb when the test is carried out within \halign/\valign:
      \exp_after:wN \use_i:nn \exp_after:wN {%
        \exp_after:wN \exp_after:wN \exp_after:wN \exp_end:
        \exp:w \exp_after:wN \use_ii:nn
        \token_to_str:N { \UD_CheckWhetherLeadingExplicitSpace:w#1##1#2 }{}
      }{}
    }
  }
  \cs_new:Npn \UD_CheckWhetherLeadingExplicitSpace:w ##1#2 {
    \tl_if_empty:oTF {\use_i:nn{}##1}
    {\use_ii_i:nn{\use_i:nn}}{\use_ii_i:nn{\use_ii:nn}}
    {\exp_after:wN\exp_after:wN\exp_after:wN\exp_end:
     \exp_after:wN\exp_after:wN\exp_after:wN}
     \exp_after:wN\use_ii:nn\exp_after:wN{\token_to_str:N}
  }%
  %%-----------------------------------------------------------------------------
}
\exp_args:Nno\use:n{\exp_args:No\UD_ExtractFirstSpaceDelimitedArg:n}
{\exp_after:wN \exp_after:wN  \tex_ifnum:D 0=0\tex_fi:D }{~}
%%%
%%-----------------------------------------------------------------------------
%% Loop for trimming all leading explicit space tokens from argument
%%
%%   \TrimAllLeadingSpaces{<argument>}{<tokens to prepend>}
%%
%% delivers  <tokens to prepend>{<argument>}   , but with all leading spaces of
%% <argument> removed.
%%.............................................................................
\cs_new:Npn \TrimAllLeadingSpaces #1 {
  \CheckWhetherLeadingExplicitSpace{#1}{
    \exp_args:No \TrimAllLeadingSpaces {\UD_GobbleKnownFirstSpace:w #1}
  }{ \use_ii_i:nn{{#1}} }
}
%----------------------------------------------------------------------------------------
%% Loop for trimming all trailing explicit space tokens from argument
%%
%%   \TrimAllTrailingSpaces{<argument>}{<tokens to prepend>}
%%
%% delivers  <tokens to prepend>{<argument>}   , but with all trailing spaces 
%% of <argument> removed.
%%
%% Algorithm:
%% Initate a loop with a tail-recursive macro with 3 arguments:
%% 1. <Space from previous iteration>. Initially empty.
%% 2. <Argument without trailing spaces gathered so far>. Initially empty.
%% 3. <Remaining argument to process>. Initially <Arg><space>.
%%
%% If <Remaining argument to process> is not blank:
%% Call \trimalltrailingspaces again, with
%%  <Argument without trailing spaces gathered so far>=
%%     <Argument without trailing spaces gathered so far>+<Space from previous iteration>+
%%     <Extraction of 1st space-delimited Arg from <Remaining argument to process> >;
%%  <Remaining argument to process>=<Remaining argument to process> with 1st space-delimited arg removed;
%%  <Space from previous iteration>=<explicit space token>;
%%
%% If <Remaining argument to process> is blank: 
%% Pass <Argument without trailing spaces gathered so far> as argument to
%% <tokens to prepend> .
%%.............................................................................
\cs_new:Npn \TrimAllTrailingSpaces #1 {\exp:w\UD_TrimAllTrailingSpacesLoop:www{}{}{#1~}}
\cs_new:Npn \UD_TrimAllTrailingSpacesLoop:www #1#2#3 {
  \tl_if_blank:nTF {#3}{\exp_after:wN \exp_end: \use_ii_i:nn{{#2}}}{
    \exp_after:wN \exp_after:wN \exp_after:wN \use_ii_i:nn
    \exp_after:wN \exp_after:wN \exp_after:wN {
      \UD_RemoveFirstSpaceDelimitedArg:n {#3}
    }{
      \exp_after:wN \use_ii_i:nn \exp_after:wN { \exp_after:wN {
        \exp:w \exp_after:wN \exp_after:wN \exp_after:wN \use_ii_i:nn
        \UD_ExtractFirstSpaceDelimitedArg:n {#3}{\exp_end: #2#1}
      }}{\UD_TrimAllTrailingSpacesLoop:www{~}}
    }
  }
}
%%-----------------------------------------------------------------------------
\cs_new:Npn \UD_ExtractWords:nn #1#2 { 
  \exp:w  \TrimAllLeadingSpaces { #2 }
          { \TrimAllTrailingSpaces }
          { \UD_ExtractWordsloop:nnnn {}{} }
          { #1 } 
}
\cs_new:Npn \UD_ExtractWordsloop:nnnn #1#2#3#4 {
%  % #1 stuff to prepend , #2 gathered so far, #3 remaining list, #4 number
  \int_compare:nNnTF {(#4)} > {(0)} 
     {
       \tl_if_empty:nTF  {#3} { \exp_end: #2 }{
         \CheckWhetherLeadingExplicitSpace{#3}{
           \exp_after:wN \use_ii_i:nn \exp_after:wN { \exp_after:wN { \UD_GobbleKnownFirstSpace:w #3 } }
           { \UD_ExtractWordsloop:nnnn {#1}{#2}}{#4}
         }{
           \exp_after:wN \exp_after:wN \exp_after:wN \use_ii_i:nn
           \exp_after:wN \exp_after:wN \exp_after:wN { 
           \exp_after:wN \exp_after:wN \exp_after:wN   {\int_eval:n {((#4)-1)}} 
           }{
             \exp_args:Nno \use:n { \exp_args:No \use_ii_i:nn } {
                \UD_RemoveFirstSpaceDelimitedArg:n {#3}
             }{
               \exp_args:No \use_ii_i:nn { \exp_after:wN {
                  \exp:w
                  \exp_after:wN \exp_after:wN \exp_after:wN
                  \use_ii_i:nn \UD_ExtractFirstSpaceDelimitedArg:n {#3}{\exp_end: #2#1}
               }}{
                  \UD_ExtractWordsloop:nnnn {~}
               }
             }
           }
         }
       }
     }
     {\exp_end: #2}
}
\cs_new:Npn \UD_firstwordscase:nn #1#2 {
  \exp_args:Nno \use:n { \exp_args:No\str_case:nnF } { \UD_ExtractWords:nn {#1}{#2} }
}
\cs_generate_variant:Nn \UD_firstwordscase:nn { ne }
\cs_new:Npn \firstwordscase #1#2 { \UD_firstwordscase:ne {#1}{\text_expand:n {#2}} }
\ExplSyntaxOff

\documentclass{article}

\newcommand{\test}{1. Book2 p3} % just for testing

\begin{document}

\firstwordscase{2}{1. Book1 p3}{
  {1. Book1}{The second argument belongs to 1. Book1.}
  {1. Book2}{The second argument belongs to 1. Book2.}
}{The second argument doesn't belong to any of the further.}
    
\firstwordscase{2}{1. Book2 p3}{
  {1. Book1}{The second argument belongs to 1. Book1.}
  {1. Book2}{The second argument belongs to 1. Book2.}
}{The second argument doesn't belong to any of the further.}
    
\firstwordscase{2}{\test}{
  {1. Book1}{The second argument belongs to 1. Book1.}
  {1. Book2}{The second argument belongs to 1. Book2.}
}{The second argument doesn't belong to any of the further.}

\firstwordscase{2}{2. Book1 p1}{
  {1. Book1}{The second argument belongs to 1. Book1.}
  {1. Book2}{The second argument belongs to 1. Book2.}
}{The second argument doesn't belong to any of the further.}

\firstwordscase{2}{2. Book1 p1}{
  {2. Book1}{The second argument belongs to 2. Book1.}
  {1. Book2}{The second argument belongs to 1. Book2.}
}{The second argument doesn't belong to any of the further.}

\def\spaceimport#1{\firstwordscase{2}{2.#1#1#1#1Book1#1#1#1#1p1}}
\spaceimport{ }{
  {2. Book1}{The second argument belongs to 2. Book1.}
  {1. Book2}{The second argument belongs to 1. Book2.}
}{The second argument doesn't belong to any of the further.}


\firstwordscase{1}{1 A a i I - second argument }{
  {1}{The second argument belongs to 1.}
  {2}{The second argument belongs to 2.}
}{The second argument doesn't belong to any of the further.}

\firstwordscase{1}{2 A a i I - second argument }{
  {1}{The second argument belongs to 1.}
  {2}{The second argument belongs to 2.}
}{The second argument doesn't belong to any of the further.}

\firstwordscase{2}{1 A a i I - second argument }{
  {1 A}{The second argument belongs to 1 A.}
  {1 B}{The second argument belongs to 1 B.}
  {2 A}{The second argument belongs to 2 A.}
  {2 B}{The second argument belongs to 2 B.}
}{The second argument doesn't belong to any of the further.}

\firstwordscase{2}{2 B a i I - second argument }{
  {1 A}{The second argument belongs to 1 A.}
  {1 B}{The second argument belongs to 1 B.}
  {2 A}{The second argument belongs to 2 A.}
  {2 B}{The second argument belongs to 2 B.}
}{The second argument doesn't belong to any of the further.}

\firstwordscase{3}{1 A a i I - second argument }{
  {1 A a}{The second argument belongs to 1 A a.}
  {1 B a}{The second argument belongs to 1 B a.}
  {2 A a}{The second argument belongs to 2 A a.}
  {2 B a}{The second argument belongs to 2 B a.}
  {1 A b}{The second argument belongs to 1 A b.}
  {1 B b}{The second argument belongs to 1 B b.}
  {2 A b}{The second argument belongs to 2 A b.}
  {2 B b}{The second argument belongs to 2 B b.}
}{The second argument doesn't belong to any of the further.}

\firstwordscase{3}{ 2 B a i I - second argument }{
  {1 A a}{The second argument belongs to 1 A a.}
  {1 B a}{The second argument belongs to 1 B a.}
  {2 A a}{The second argument belongs to 2 A a.}
  {2 B a}{The second argument belongs to 2 B a.}
  {1 A b}{The second argument belongs to 1 A b.}
  {1 B b}{The second argument belongs to 1 B b.}
  {2 A b}{The second argument belongs to 2 A b.}
  {2 B b}{The second argument belongs to 2 B b.}
}{The second argument doesn't belong to to any of the further.}

\end{document}

在此处输入图片描述

相关内容