LaTeX count number of occurrences of a character in a string

Using expl3 you can split the token list into items and then count the items (less 1):

2
4

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
% \CountSubStr{<substring>}{<string>}
\NewDocumentCommand{\CountSubStr}{ m m }{
  \seq_set_split:Nnn \l_tmpa_seq { #1 } { #2 }
  \int_eval:n {(\seq_count:N \l_tmpa_seq) - 1 }
}
\ExplSyntaxOff

\begin{document}

\CountSubStr{~}{This~is a ~test}% 2

\CountSubStr{yes}{a yes b yes c yes deyesfg yehs ij}% 4

\end{document}

For good measure, a LuaLaTeX-based solution:

enter image description here

\documentclass{article}
\usepackage{luacode} % for '\luastring' and '\luaexec' macros
\newcommand\tildecount[1]{\luaexec{
   _ , count = string.gsub ( \luastring{#1} , "~" , "~" )
   tex.sprint ( count ) }}
\begin{document}
\tildecount{This~is a ~test}

\tildecount{~~~~----&&&&****____####~~~~$$$$~~~~}
\end{document}

Addendum: The \tildecount macro can easily be generalized to take a second input, viz., the string whose occurrences should be counted. The code for the generalized macro would be as follows:

\newcommand\StringCount[2]{\luaexec{
   _ , count = string.gsub ( \luastring{#2} , \luastring{#1} , "" )
   tex.sprint ( count ) }}

This macro may be used, for instance, as

\StringCount{yes}{a yes b yes c yes desyesfg mess ij}

(result: 4) or as

\StringCount{es}{a yes b mesh c best less xxDavieszz mess ij} 

(result: 6).

Tags:

Strings