Sponsoring The Perl Toolchain Summit 2025: Help make this important event another success Learn more

// NEW CODE
#include "jpcre2.hpp"
#include <iostream>
typedef jpcre2::select<char> jp;
int main() {
// SAMPLE CODE
//Check if string matches the pattern
/*
* The following uses a temporary Regex object.
*/
std::cout << "\n\n" << "[[[ DEBUG ]]] BEFORE MATCH 1" << "\n\n";
if(jp::Regex("(\\d)|(\\w)").match("I am the subject")) {
std::cout << "\nmatched";
}
std::cout << "\n\n" << "[[[ DEBUG ]]] AFTER MATCH 1" << "\n\n";
/*
* Using the modifier S (i.e jpcre2::JIT_COMPILE) with temporary object may or may not give you
* any performance boost (depends on the complexity of the pattern). The more complex
* the pattern gets, the more sense the S modifier makes.
*/
//If you want to match all and get the match count, use the action modifier 'g':
std::cout << "\n\n" << "[[[ DEBUG ]]] BEFORE MATCH 2" << "\n\n";
std::cout << "\n" << jp::Regex("(\\d)|(\\w)","m").match("I am the subject","g");
std::cout << "\n\n" << "[[[ DEBUG ]]] AFTER MATCH 2" << "\n\n";
size_t count;
/*
* Modifiers passed to the Regex constructor or with compile() function are compile modifiers
* Modifiers passed with the match() or replace() functions are action modifiers
*/
// Substrings/Captured groups:
/*
* *** Getting captured groups/substring ***
*
* captured groups or substrings are stored in maps/vectors for each match,
* and each match is stored in a vector.
* Thus captured groups are in a vector of maps/vectors.
*
* PCRE2 provides two types of substrings:
* 1. numbered (indexed) substring
* 2. named substring
*
* For the above two, we have two vectors respectively:
* 1. jp::VecNum (Corresponding vector: jp::NumSub)
* 2. jp::VecNas (Corresponding map: jp::MapNas)
*
* Another additional vector is available to get the substring position/number
* for a particular captured group by name. It's a vector of name to number maps
* * jp::VecNtN (Corresponding map: jp:MapNtN)
*/
// ***** Get numbered substring ***** ///
jp::VecNum vec_num;
jp::RegexMatch rm;
jp::Regex re("(\\w+)\\s*(\\d+)","m");
count =
jp::RegexMatch(&re).setSubject("I am 23, I am digits 10")
.setModifier("g")
.setNumberedSubstringVector(&vec_num)
.match();
/*
* count (the return value) is guaranteed to give you the correct number of matches,
* while vec_num.size() may give you wrong result if any match result
* was failed to be inserted in the vector. This should not happen
* i.e count and vec_num.size() should always be equal.
*/
std::cout<<"\nNumber of matches: "<<count/* or vec_num.size()*/;
//Now vec_num is populated with numbered substrings for each match
//The size of vec_num is the total match count
//vec_num[0] is the first match
//The type of vec_num[0] is jp::NumSub
std::cout<<"\nTotal match of first match: "<<vec_num[0][0];
std::cout<<"\nCaptured group 1 of first match: "<<vec_num[0][1];
std::cout<<"\nCaptured group 2 of first match: "<<vec_num[0][2];
//captured group 3 doesn't exist, (with operator [] it's a segfault)
//std::cout<<"\nCaptured group 3 of first match: "<<vec_num[0][3];
//Using at() will throw std::out_of_range exception
//~ try {
//~ std::cout<<"\nCaptured group 3 of first match: "<<vec_num[0].at(3);
//~ } catch (const std::out_of_range& e) {
//~ std::cerr<<"\n"<<e.what();
//~ }
//There were two matches found (vec_num.size() == 2) in the above example
std::cout<<"\nTotal match of second match: "<<vec_num[1][0]; //Total match (group 0) from second match
std::cout<<"\nCaptured group 1 of second match: "<<vec_num[1][1]; //captured group 1 from second match
std::cout<<"\nCaptured group 2 of second match: "<<vec_num[1][2]; //captured group 2 from second match
// ***** Get named substring ***** //
jp::VecNas vec_nas;
jp::VecNtN vec_ntn; // We will get name to number map vector too
re.compile("(?<word>\\w+)\\s*(?<digit>\\d+)","m");
count =
jp::RegexMatch(&re).setSubject("I am 23, I am digits 10")
.setModifier("g")
//.setNumberedSubstringVector(vec_num) // We don't need it in this example
.setNamedSubstringVector(&vec_nas)
.setNameToNumberMapVector(&vec_ntn) // Additional (name to number maps)
.match();
std::cout<<"\nNumber of matches: "<<vec_nas.size()/* or count */;
//Now vec_nas is populated with named substrings for each match
//The size of vec_nas is the total match count
//vec_nas[0] is the first match
//The type of vec_nas[0] is jp::MapNas
std::cout<<"\nCaptured group (word) of first match: "<<vec_nas[0]["word"];
std::cout<<"\nCaptured group (digit) of first match: "<<vec_nas[0]["digit"];
//Trying to access a non-existence named substirng with [] operator will give you empty string
//If the existence of a substring is important, use the std::map::find() or std::map::at()
//(>=C++11) function to access map elements.
/* //>=C++11
try{
///This will throw exception because the substring name 'name' doesn't exist
std::cout<<"\nCaptured group (name) of first match: "<<vec_nas[0].at("name");
} catch(const std::logic_error& e){
std::cerr<<"\nCaptured group (name) doesn't exist";
}*/
//There were two matches found (vec_nas.size() == 2) in the above example
std::cout<<"\nCaptured group (word) of second match: "<<vec_nas[1]["word"];
std::cout<<"\nCaptured group (digit) of second match: "<<vec_nas[1]["digit"];
//Get the position (number) of a captured group name (that was found in match)
std::cout<<"\nPosition of captured group (word) in first match: "<<vec_ntn[0]["word"];
std::cout<<"\nPosition of captured group (digit) in first match: "<<vec_ntn[0]["digit"];
/*
* Replacement Examples
* Replace pattern in a string with a replacement string
*
* The Regex::replace() function can take a subject and replacement string as argument.
*
* You can also pass the subject with setSubject() function in method chain,
* replacement string with setReplaceWith() function in method chain, etc ...
* A call to RegexReplace::replace() in the method chain will return the resultant string
*/
std::cout<<"\n"<<
//replace first occurrence of a digit with @
jp::Regex("\\d").replace("I am the subject string 44", "@");
std::cout<<"\n"<<
//replace all occurrences of a digit with @
jp::Regex("\\d").replace("I am the subject string 44", "@", "g");
//swap two parts of a string
std::cout<<"\n"<<
jp::Regex("^([^\t]+)\t([^\t]+)$")
.replace("I am the subject\tTo be swapped according to tab", "$2 $1");
//Doing the above with method chain:
re.compile("^([^\t]+)\t([^\t]+)$");
jp::RegexReplace(&re).setSubject("I am the subject\tTo be swapped according to tab")
.setReplaceWith("$2 $1")
.replace();
// NEW CODE
}