How to check if a variable contains a word in plain TeX?
The following example uses package kvsetkeys
to get a parser for lists with comma separated entries:
\input kvsetkeys.sty % parser for comma separated lists
\input ltxcmds.sty % helper macros
\catcode`\@=11 % \makeatletter
\newif\ifkey@found
% \testkeywordinlist{keyword}{keyword list}{true}{false}
\def\testkeywordinlist#1#2{%
\edef\key@word{#1}%
\edef\key@list{#2}%
\key@foundfalse
\expandafter\comma@parse\expandafter{\key@list}{%
\ifx\comma@entry\key@word
\key@foundtrue
\comma@break
\fi
\ltx@gobble
}%
\ifkey@found
\expandafter\ltx@firstoftwo
\else
\expandafter\ltx@secondoftwo
\fi
}
\catcode`\@=12 % \makeatother
\def\keywords{computers, business, biology, fine art, literature, zoology}
\testkeywordinlist{zoology}{\keywords}{%
\immediate\write16{* "zoology" found.}%
}{%
\immediate\write16{* "zoology" not found.}%
}
\end
Result:
- "zoology" found.
You can use functional-style programming to build a fully-expandable version of map
and string comparison. This however requires e-TeX support. Here I am using \pdfstrcmp
to compare strings, so this solution is specific to pdfTeX.
\def\map#1#2{%
\domap{#1}#2,\end}
\def\domap#1#2,#3\end{%
#1{\strip#2\endstrip}%
\ifx\end#3\end\else\domap{#1}#3\end\fi}
% skips leading spaces
\def\strip#1#2\endstrip{#1#2}
% predicate (pdfTeX specific)
\def\ifstrequal#1#2#3#4{\ifnum\pdfstrcmp{#1}{#4}=0 #2\else #3\fi}
% Check if the list contains something
\def\ifinlist#1#2#3#4{%
\ifstrequal{found}{#3}{#4}{%
\map{\ifstrequal{#1}{found}{}}{#2}%
}%
}
% fully expand \map
\edef\found{%
\map
{\ifstrequal{zoology}{``zoology'' found}{}}% predicate with empty false branch
{computers, business, biology, fine art, literature, zoology}%
}
\tt\meaning\found
% fully expand \ifinlist
\edef\found{%
\ifinlist
{zoology}%
{computers, business, biology, fine art, literature, zoology}%
{TRUE}%
{FALSE}%
}
\tt\meaning\found
\bye