8

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?

0

5 Answers 5

9

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

1

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.

1

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.

3
  • Using your solution, I have managed to count a character within an argument by assigning the argument to a macro \def\labelvalue{#1}\def\coloncount{\countin*{:}{\labelvalue}}. Printing the result works fine, but unfortunately Missing number, treated as zero. <to be read again> \xparse function is not expandable is being thrown when comparing the result with an integer, e.g. \ifnum \coloncount=1. I found this link mentioning your answer, but I didn't get their suggestion to work. Do you have any suggestions on how to make this work?
    – coreuter
    Commented Jul 26, 2023 at 15:44
  • @coreuter Please, ask a new question with the details as a followup to this one.
    – egreg
    Commented Jul 26, 2023 at 15:45
  • thank you very much for your prompt reply! I have asked a new question: tex.stackexchange.com/q/692035/96582
    – coreuter
    Commented Jul 26, 2023 at 16:25
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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .