5

Let's say I have some string This~is a ~test. I need to count the number of ~ characters. Is there some way to do this in LaTeX?

7

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}
3

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).

0

Consider substr.sty.

Add \usepackage{substr} and try

\CountSubStrings{~}{This~is a ~test} % -> 2

or

\newcounter{foo}
\SubStringsToCounter{foo}{;}{1;2;3;4}
\stepcounter{foo}
% \thefoo -> 4
0

A listofitems approach.

\documentclass{article}
\usepackage{listofitems}
\newcommand\countem[2]{%
  \setsepchar{#1}%
  \readlist\countlist{#2}%
  \the\numexpr\listlen\countlist[]-1\relax
}
\begin{document}
\countem{~}{This~is a ~test}

\countem{es}{a yes b mesh c best less xxDavieszz mess ij} 
\end{document}

The MWE gives the appropriate answers of 2 and 6.

0

You can use regular expressions:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\countin}{smm}
 {% #1 = * if searching in a macro
  % #2 = string to search
  % #3 = token list to search in
  \IfBooleanTF { #1 }
   {
    \bruoga_countin:nV { #2 } #3
   }
   {
    \bruoga_countin:nn { #2 } { #3 }
   }
 }
\cs_new_protected:Nn \bruoga_countin:nn
 {
  \regex_count:nnN { #1 } { #2 } \l_tmpa_int
  \int_to_arabic:n { \l_tmpa_int }
 }
\cs_generate_variant:Nn \bruoga_countin:nn { nV }
\ExplSyntaxOff

\begin{document}

\newcommand{\mytl}{This~is a ~test}

\countin{~}{This~is a ~test}

\countin*{~}{\mytl}

\countin{t}{This~is a ~test}

\countin{[Tt]}{This~is a ~test}

\countin{[aeiou]}{This~is a ~test}

\end{document}

This prints

2
2
2
3
4

The syntax for (simple) regular expressions is quite standard.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.