4

Question: Given a string of ordinary text characters, delete anything that is not a numeral. Save it as a macro for further processing. The remaining numerals must be in order written, and must have their usual catcode 12.

In POSIX shell with sed, I could write:

mystring="Special: Five (5) bananas for \$1.50."
justnumerals="$(echo $mystring | sed 's/[^0-9]*//g')"
echo "$justnumerals" # Result: 5150

That is routine for sed on command line, but to do it within TeX... expl3 regular expressions to the rescue! Alas, after looking at file interface3.pdf in the l3kernel documentation, I am lost. Problem is that there is an interaction between escape codes, and I, mere sniveling user, cannot follow them.

More generally, is there a user-land tutorial (rather than a programmer-land tutorial) for expl3 regular expressions somewhere? I did not find one via general Internet search. What I did find was math-intensive, except for a helpful previous question Regular Expression using `expl3`

Note: I compile only with lualatex, if that makes a difference. But I did not think it mattered, so I did not put that tag for the question.

3
  • For (most of) L3 LuaTeX vs pdfTeX doesn't make much of a difference on the user level, certainly not for regex, so omitting it is fine here :)
    – Skillmon
    Apr 14 at 19:27
  • @Skillmon for the question but some answers might work better in luatex:-) Apr 14 at 20:58
  • @DavidCarlisle certainly, yes :)
    – Skillmon
    Apr 15 at 6:19

3 Answers 3

4

The equivalent of your sed call is actually pretty straight forward in l3regex:

\ExplSyntaxOn
\tl_new:N \l_rallg_mystring_tl
\tl_set:Nn \l_rallg_mystring_tl { Special:~ Five~ (5)~ bananas~ for~ \$1.50. }
\regex_replace_all:nnN { [^0-9] } {} \l_rallg_mystring_tl
\tl_analysis_show:N \l_rallg_mystring_tl
\stop

Category codes of your numerals will be unchanged. It'll print to the terminal/log:

The token list \l_rallg_mystring_tl contains the tokens:
>  5 (the character 5)
>  1 (the character 1)
>  5 (the character 5)
>  0 (the character 0).
1
  • 1
    I accept this because it directly adressed the question as-asked, so it will be useful to others via topic search. My general usage might be better addressed via other answers.
    – user287367
    Apr 14 at 21:11
3

While I realize your question is an expl3 question, I nonetheless show here how the desired result may be achieved with a token cycle.

Catcodes of the numerals are unchanged, and the presence of numbers in groups poses no problem to extracting them.

\documentclass{article}
\usepackage{tokcycle}
\stripgroupingtrue% STRIPS cat-1,2 BRACES FROM OUTPUT
\tokcycleenvironment\justnumerals
  {\ifnum`##1>`/ \ifnum`##1<`:\addcytoks{##1}\fi\fi}% SEEKS NUMBER CHARS ONLY
  {\processtoks{##1}}% PROCESSES GROUP CONTENT
  {}% STRIPS MACROS
  {}% STRIPS SPACES
\begin{document}
\def\mystring{Special: Five (5) bananas for \$1.50. 
  \textit{Numbers 2 and 4 in a group} Täüt}
\expandafter\justnumerals\mystring\endjustnumerals

Confirm braces stripped: \detokenize\expandafter{\the\cytoks}
\end{document}

enter image description here

3
  • Interesting. I do not fully grasp TeX tokens, but this might be useful.
    – user287367
    Apr 14 at 21:12
  • @rallg The package allows you to cycle through the tokens of the environment (or argument) and to do something on a token by token basis, the something being based on user-specified directives. Apr 14 at 22:24
  • Yes, I can see how that could be useful for various purposes. You mentioned this in another question I asked, and that was also interesting. I will look at this in more detail later. It seems to have a similar concept as the OpenType "chained context alternatives" which can look back/ahead when making a decision about a character.
    – user287367
    Apr 15 at 0:58
3

As you are using luatex anyway you could use Lua patterns that are closer to what you are used to, and probably thousands of times quicker than l3regex.

enter image description here

\documentclass{article}

\makeatletter
\def\foo#1{\directlua{%
    tex.print(string.gsub([[\detokenize{#1}]],"[^\@percentchar d]","") .. "")}}
\makeatother

\begin{document}

\foo{Special: Five (5) bananas for \$1.50.}

\end{document}
1
  • This is actually the right way "for me." But since that is not the way I asked the question, I did not set it as the accepted answer. Once again, lualatex has the power.
    – user287367
    Apr 14 at 21:13

You must log in to answer this question.