搜索字符串

搜索字符串

是否有 TeX 宏(纯文本或 AmS-TeX)可以搜索特定字符串?具体来说,我想要一个宏,它是 if/then 宏的一部分,其形式为,如果给定的字符串 xyz 出现在单词中,则 ...,否则为其他内容。

答案1

在纯 TeX 中

\input listofitems
\def\findstring#1#2#3#4{%
  \setsepchar{#1}%
  \readlist\mylist{#2}%
  \ifnum\mylistlen>1\relax#3\else#4\fi
}
\findstring{abc}{My string ab*c does not contain it}{Found}{Not Found}

\findstring{abc}{My string abc does contain it}{Found}{Not Found}
\bye

在此处输入图片描述

答案2

这是( ) 和( )expl3的副本。前者考虑了 catcode 的差异,而后者将所有内容视为 catcode-12(空格除外,空格为 catcode-10)。语法是。宏定义一个由 分隔的辅助,然后使用它来检查 是否包含。在表格单元格中以及对于空参数使用此宏可以提高安全性(有关实现详细信息,请参阅 的文档)。\tl_if_in:nn\IfContainedIn\str_if_in:nn\StrIfContainedIn\StrIfContainedIn{<string>}{<substring>}{<true>}{<false>}<substring><string><substring>l3tl

如果您使用带有 ε-TeX 的 TeX 引擎(\detokenize需要从参数中生成字符串并进行稳健\IfEmpty测试),那么:

\catcode`\@=11
\def\@firstoftwo#1#2{#1}
\def\@secondoftwo#1#2{#2}
\def\return@if@false{\expandafter\@secondoftwo\romannumeral}
\def\return@if@true{\expandafter\@firstoftwo\romannumeral}
\chardef\exp@end=0
%
\def\IfEmpty#1{%
  \if\relax\detokenize{#1}\relax
    \return@if@true
  \else
    \return@if@false
  \fi\exp@end}
%
\def\IfContainedIn#1#2{%
  \relax\iffalse{\fi
  \def\if@contained@aux##1#2{}%
  \expandafter\IfEmpty\expandafter{\if@contained@aux#1{}{}#2}%
    {\return@if@false}{\return@if@true}%
  \iffalse}\fi
  \exp@end}
%
\def\StrIfContainedIn#1#2{%
  \edef\@@tmpa{\noexpand\IfContainedIn
    {\detokenize{#1}}{\detokenize{#2}}}\@@tmpa
    {\return@if@true}{\return@if@false}%
  \exp@end}
\catcode`\@=12

\StrIfContainedIn{hello}{el}{T}{F}
\StrIfContainedIn{hello}{le}{T}{F}

\bye

否则,如果您使用的是 Knuth 的 TeX,那么您需要一个 poorman 的\detokenize

\def\@firstoftwo#1#2{#1}
\def\@secondoftwo#1#2{#2}
\def\strip@prefix#1>{}
\newtoks\myscratchtoks
\long\def\poorman@detokenize#1#2{%
  \myscratchtoks{#2}\edef#1{\the\myscratchtoks}%
  \edef#1{\expandafter\strip@prefix\meaning#1}}%
\def\return@if@false{\expandafter\@secondoftwo\romannumeral}
\def\return@if@true{\expandafter\@firstoftwo\romannumeral}
\chardef\exp@end=0
%
\def\IfEmpty#1{%
  \poorman@detokenize\@@tmpa{#1}%
  \if\relax\@@tmpa\relax
    \return@if@true
  \else
    \return@if@false
  \fi\exp@end}
%
\def\IfContainedIn#1#2{%
  \relax\iffalse{\fi
  \def\if@contained@aux##1#2{}%
  \expandafter\IfEmpty\expandafter{\if@contained@aux#1{}{}#2}%
    {\return@if@false}{\return@if@true}%
  \iffalse}\fi
  \exp@end}
%
\def\StrIfContainedIn#1#2{%
  \poorman@detokenize\@@tmpa{#1}%
  \poorman@detokenize\@@tmpb{#2}%
  \edef\@@tmpa{\noexpand\IfContainedIn
    {\@@tmpa}{\@@tmpb}}\@@tmpa
    {\return@if@true}{\return@if@false}%
  \exp@end}
\catcode`\@=12

\StrIfContainedIn{hello}{el}{T}{F}
\StrIfContainedIn{hello}{le}{T}{F}

\bye

答案3

与我的其他答案不同的方法。这使用tokcycle,而不是listofitems。此处扩展的功能是能够深入查看组内容以查找所需字符串,而我的其他更简单的答案则无法做到这一点。同样,宏名称和组可以成为搜索字符串的一部分。

\input tokcycle
\def\findinstring#1#2#3#4{\begingroup%
  \stripgroupingtrue
  \runcount=0\relax%
  \tokcycle{\nextctltok{##1}}
           {\nextctltok{\opengroup}\processtoks{##1}\nextctltok{\closegroup}}
           {\nextctltok{##1}}
           {\nextctltok{\tcspace}}{#1}%
  \edef\numlet{\the\runcount}%
  \expandafter\def\expandafter\searchword\expandafter{\the\cytoks}%
  \aftertokcycle{\expandafter\ifx\matchfound T#3\else#4\fi}%
  \runcount=0\relax%
  \def\matchfound{F}%
  \tokcycle{\nextcmptok{##1}}
           {\nextcmptok{\opengroup}\processtoks{##1}\nextcmptok{\closegroup}}
           {\nextcmptok{##1}}
           {\nextcmptok{\tcspace}}{#2}%
  \endgroup}
\newcount\runcount
\catcode`@=11 
\def\rotcytoks#1{\cytoks\expandafter\expandafter\expandafter{%
  \expandafter\tc@gobble\the\cytoks#1}}
\catcode`@=12 
\def\testmatch#1{\ifx#1\searchword\gdef\matchfound{T}\fi}%
\def\rotoradd#1#2{\runcount=\numexpr\runcount+1\relax%
  \ifnum\the\runcount>\numlet\relax#1\else#2\fi\expandafter
  \def\expandafter\tmp\expandafter{\the\cytoks}}
\def\nextcmptok#1{\rotoradd{\rotcytoks{#1}}{\addcytoks{#1}}\testmatch{\tmp}}
\def\nextctltok#1{\runcount=\numexpr\runcount+1\relax\addcytoks{#1}}

\findinstring{a\notmymac{b c}}{gf{vf{a\mymac{b c}g}gh}hn}{Found}{Not Found}

\findinstring{a\mymac{b c}}{gf{vf{a\mymac{b c}g}gh}hn}{Found}{Not Found}
\bye

在此处输入图片描述

相关内容