9

Environment that counts words inside does like the title says, but prints the words that it counts, too. Is there a way to count the words without printing them?

\countCommand{Four and twenty blackbirds} % should print: 4
4

If you mean counting the spaces in the argument, at all brace levels, with l3regex you can do it:

\documentclass{article}
\usepackage{xparse,l3regex}

\ExplSyntaxOn
\NewDocumentCommand{\countwords}{+m} % allow \par (or blank lines in the argument)
 {
  \regex_count:nnN { \s } { #1 } \l_corneli_words_int
  \int_to_arabic:n { \l_corneli_words_int + 1 }
 }
\int_new:N \l_corneli_words_int
\ExplSyntaxOff

\begin{document}
\countwords{Four and twenty blackbirds}

\countwords{Four \emph{and twenty} blackbirds}
\end{document}

This prints

4
4

3
  • This seems the most robust so far for dealing with included LaTeX markup (environments, citations, hyperref). It doesn't like paragraph breaks, but that seems like a minor point. – Joe Corneli Mar 3 '14 at 13:16
  • @JoeCorneli Without a complete specification it's difficult to do more. For allowing \par, just type {+m} instead of {m} in the definition of \countwords. – egreg Mar 3 '14 at 13:18
  • Cool! OK, I think this answer wins the checkmark. – Joe Corneli Mar 3 '14 at 13:23
6

Here's a simple solution using xstring

% arara: pdflatex
\documentclass{article}

\usepackage{xstring}

\newcommand{\wordcount}[1]{\StrCount{#1}{\space}[\tmp]%
\number\numexpr\tmp+1\relax}
\begin{document}

\wordcount{Four and twenty blackbirds}
\end{document}

It works by counting the spaces, and then adding 1; it works fine even when there are multiple spaces between words, so you can use

\wordcount{Four    and     twenty     blackbirds}

and still get 4. However if you try anything like

\wordcount{ Four and twenty blackbirds}
\wordcount{Four and twenty blackbirds }
\wordcount{ Four and twenty blackbirds }

then you won't get the expected result. You can fix this using, for example, something like the following:

\newcount\cmh
\newcommand{\wordcount}[1]{%
\StrCount{#1}{\space}[\tmp]%
\cmh=\tmp%
\IfBeginWith{#1}{\space}{\advance\cmh by -1\relax}{}%
\IfEndWith{#1}{\space}{\advance\cmh by -1\relax}{}%
\number\numexpr\cmh+1\relax
}
3
  • ah, \space - that's helpful! Very useful piece of information that :-) – Joe Corneli Mar 3 '14 at 3:23
  • @JoeCorneli glad it helped ;) it works fine with multiple spaces between words, too! – cmhughes Mar 3 '14 at 3:26
  • ... and newlines too! Impressed! – Joe Corneli Mar 3 '14 at 3:30
3
\documentclass{article}
\usepackage{readarray}
\begin{document}
\getargsC{Four and twenty blackbirds}
Words = \narg\par
The words are \argi, \argii, \argiii, and \argiv.
\end{document} 

Thus, based on this MWE, \def\wordcount#1{\getargsC{#1}\narg} would suffice to answer the OP's question. Note that \getargsC is functionally equivalent but far superior in speed to the \getargs macro of the stringstrings package.

2
  • This one has the benefit of being more robust vis a vis hyperref, although neither this answer nor the other one are working with things like quoting environments. Indeed, \wordcount{\emph{Four and twenty blackbirds}} gives 1 as the answer. – Joe Corneli Mar 3 '14 at 4:21
  • @JoeCorneli Indeed, \emph{...} is treated as a single word, precisely because that is the way LaTeX treats groups (think about how we define arguments); however, \itshape four and twenty blackbirds would pickup the proper number of words. – Steven B. Segletes Mar 3 '14 at 4:25

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.