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)


\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 { 

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

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

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


   { \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

\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 }''
\cs_generate_variant:Nn \tl_trim_spaces:n { f }


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


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

enter image description here

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

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.