# using regex to extract two values (send to macro variables) of unique multiple occurences

I read several key values from a document with bible passages written in spanish like this

1 Corintios 2:4-5; Mateo 15:1-10;Salmos 118:16


I want to extract the citations in each reference (could be one or more than one) and for each citation inside the reference I need to split it to get the "book name" and "chapter" in order to send both to special index. Book names may be preceeded by numbers. For each occurrence I want to "store" the values into l_hpbook and l_hpchapter variables. I am able to use the right regex expression, but not able to store the values in the respective macro variable lp_hpbook and l_hpchapter. Any hints? (functionality not available in bibleref, there is not even an spanish package)

\documentclass{article}
\usepackage{expl3}
\usepackage{l3regex}

\ExplSyntaxOn
\tl_new:N \l_hpsplit_tl

\cs_new:Npn \hpsplit #1 {
% Purpose: Extract all words that are followed by a space + number
%          optionally preceded by a number and space
% Return: All matches are stored in a global token \hpmatches_tl
\str_new:N \l_hpbook
\int_new:N \l_hpchapter

\tl_new:N \l_holdmatches

\int_new:N \l_hpmatch_int
\tl_set:Nn \l_hpsplit_tl {#1}

% This statement DOES NOT work .  Count of matches not stored in variable
% Count \l_hpmatch_int % Output generates error: Missing number
\regex_count:nnN {\d+\s\w+\s\d+|\w+\s\d+ } { #1 } \l_hpmatch_int
%    Count \l_hpmatch_int % Output generates error: Missing number

% Splits multiple citations: book name and chapter number retrieved
% This statement WORKS!
\regex_extract_all:nnN{ \d+\s\w+\s\d+|\w+\s\d+} { #1 } \l_holdmatches%
\seq_map_inline:Nn \l_holdmatches {
item:~##1\par%

% Extract the book name of a single citation
\regex_extract_once:nnN{ \d+\s\w+|\w+} { ~##1 } \l_hpbook%
%       \l_hpbook % this one generates error

% Extract the book's chapter from a single citation
% by finding the last occurrence of space and digits
\regex_extract_once:nnN{(?!.*\s\d)\d+} { ~##1 } \l_hpchapter%
%       \l_hpchapter   % this one generates error if uncommented.

% I want to use these two variables as follows:
% \index{\lp_hpbook!lp_hpchapter!\articlename}
}%

\tl_use:N \l_hpsplit_tl

%    \hpvar{\seq_map_inline:Nn \l_holdmatch {~##1\par }}%
}
\ExplSyntaxOff

\begin{document}
% Will read several references from book like this
% Need to obtain 'book name' separate from chapter
\hpsplit{1 Corintios 2:4-5; Mateo 15:1-10;Salmos 118:16}
\end{document}


In my opinion it is best to first split the argument at semicolons and then extract the data from each item.

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

\ExplSyntaxOn
\NewDocumentCommand{\hpsplit}{sm}
{
\IfBooleanTF{#1}
{ \hpcolos_hpsplit:V #2 }
{ \hpcolos_hpsplit:n { #2 } }
}

\seq_new:N \l__hpcolos_hpsplit_seq
\seq_new:N \l__hpcolos_entry_seq

\cs_new_protected:Nn \hpcolos_hpsplit:n
{
\seq_set_split:Nnn \l__hpcolos_hpsplit_seq { ; } { #1 }
\seq_map_function:NN \l__hpcolos_hpsplit_seq \hpcolos_hpentry:n
}
\cs_generate_variant:Nn \hpcolos_hpsplit:n { V }

\cs_new_protected:Nn \hpcolos_hpentry:n
{
\regex_split:nnN { \s* ([0-9]+)[\:0-9-]* \Z } { #1 } \l__hpcolos_entry_seq
\hpcolos_index_entry:
}

\cs_new_protected:Nn \hpcolos_index_entry:
{
Book~is~\seq_item:Nn \l__hpcolos_entry_seq { 1 }''
---
Chapter~is~\seq_item:Nn \l__hpcolos_entry_seq { 2 }''
\par
}
\cs_generate_variant:Nn \tl_trim_spaces:n { f }
\ExplSyntaxOff

\begin{document}

\hpsplit{1 Corintios 2:4-5; Mateo 15:1-10;Salmos 118:16}

\end{document}


I defined the final function \hpcolos_index_entry: to print the data, define it as you prefer.

The trick is using \regex_split:nnN that splits the given token list according to the regex: the matching part in the capturing group will be remembered, the rest discarded. So the first case will set the sequence to contain 1 Corintios and 2. The space before 2 and the verse numbers will be removed because they're not in the capturing group.

If you want to pass a macro to the command, use \hpsplit*{\foo}, where \foo expands to a list of Bible references as above.

• Almost there. Chapter is the number before the colon : So for corintios is "2" for Mateo is "15" and Salmos is "118". Apologies if I was not clear. I will study your solution and see if I will be able to extract the chapter. Thanks – hpcolos Feb 14 '17 at 2:02
• @hpcolos Try moving ) just after + – egreg Feb 14 '17 at 9:01
• not sure if the hpsplit accepts a macro variable as parameter: For example \def or \newcommand as \def\hpcolos_str{1 Corintios 2:4-5; Mateo 15:1-10;Salmos 118:16} followed by \hpsplit{\hpcolos_str} does not work Why a string as parameter is treated differently? – hpcolos Feb 15 '17 at 1:28
• @hpcolos You didn't ask for a macro as argument. However, it's easy to add support for them. – egreg Feb 15 '17 at 8:59
• Coming from other background with programming languages I thought that using macro variables will also work. In addition to understand the workaround for a macro variable as input parameter, I would like to understand the difference between a string "stored" in a global macro variable and a direct string that renders the macro variable (or a key from a pgfkeys) not readable by the "function" you created. I have been reading several good references about Tex but not able to point to the right place. Should I ask another question about support macro variable as parameter of the "function"? – hpcolos Feb 15 '17 at 12:36