Merge pull request #69 from Arkshine/update-regex

Update regex module
This commit is contained in:
Vincent Herbet
2014-07-18 18:14:56 +02:00
385 changed files with 295012 additions and 270 deletions

View File

@ -1,134 +1,372 @@
/* Regular Expression API
* (C)2004 by David "BAILOPAN" Anderson
* Licensed under the GNU General Public License.
* No warranties of any kind.
/**
* Regular Expressions API
* By the AMX Mod X Development Team
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* this program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#if defined _regex_included
#endinput
#endinput
#endif
#define _regex_included
#if AMXX_VERSION_NUM >= 175
#pragma reqlib regex
#if !defined AMXMODX_NOAUTOLOAD
#pragma loadlib regex
#endif
#pragma reqlib regex
#if !defined AMXMODX_NOAUTOLOAD
#pragma loadlib regex
#endif
#else
#pragma library regex
#pragma library regex
#endif
enum Regex
{
REGEX_MATCH_FAIL = -2,
REGEX_PATTERN_FAIL,
REGEX_NO_MATCH,
REGEX_OK
REGEX_MATCH_FAIL = -2,
REGEX_PATTERN_FAIL = -1,
REGEX_NO_MATCH = 0,
REGEX_OK = 1
};
/**
* Precompile a regular expression. Use this if you intend on using the
* same expression multiple times. Pass the regex handle returned here to
* regex_match_c to check for matches.
*
* @param pattern The regular expression pattern.
* @param errcode Error code encountered, if applicable.
* @param error Error message encountered, if applicable.
* @param maxLen Maximum string length of the error buffer.
* @param flags General flags for the regular expression.
* i = Ignore case
* m = Multilines (affects ^ and $ so that they match
* the start/end of a line rather than matching the
* start/end of the string).
* s = Single line (affects . so that it matches any character,
* even new line characters).
* x = Pattern extension (ignore whitespace and # comments).
*
* @return -1 on error in the pattern, > valid regex handle (> 0) on success.
*
* @note This handle is automatically freed on map change. However,
* if you are completely done with it before then, you should
* call regex_free on this handle.
* Flags for compiling regex expressions.
* These come directly from the pcre library and can be used in regex_compile_ex.
*/
native Regex:regex_compile(const pattern[], &ret, error[], maxLen, const flags[]="");
#define PCRE_CASELESS 0x00000001 /* Ignore Case */
#define PCRE_MULTILINE 0x00000002 /* Multilines (affects ^ and $ so that they match the start/end of a line rather than matching the start/end of the string). */
#define PCRE_DOTALL 0x00000004 /* Single line (affects . so that it matches any character, even new line characters). */
#define PCRE_EXTENDED 0x00000008 /* Pattern extension (ignore whitespace and # comments). */
#define PCRE_ANCHORED 0x00000010 /* Force pattern anchoring. */
#define PCRE_DOLLAR_ENDONLY 0x00000020 /* $ not to match newline at end. */
#define PCRE_UNGREEDY 0x00000200 /* Invert greediness of quantifiers */
#define PCRE_NOTEMPTY 0x00000400 /* An empty string is not a valid match. */
#define PCRE_UTF8 0x00000800 /* Use UTF-8 Chars */
#define PCRE_NO_UTF8_CHECK 0x00002000 /* Do not check the pattern for UTF-8 validity (only relevant if PCRE_UTF8 is set) */
#define PCRE_NEVER_UTF 0x00010000 /* Lock out interpretation of the pattern as UTF-8 */
#define PCRE_FIRSTLINE 0x00040000 /* Force matching to be before newline */
#define PCRE_DUPNAMES 0x00080000 /* Allow duplicate names for subpattern */
#define PCRE_NEWLINE_CR 0x00100000 /* Specify that a newline is indicated by a single character CR ) */
#define PCRE_NEWLINE_CRLF 0x00300000 /* specify that a newline is indicated by the two-character CRLF sequence ) Overrides the default */
#define PCRE_NEWLINE_ANY 0x00400000 /* Specify that any Unicode newline sequence should be recognized. ) newline definition (LF) */
#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* Specify that any of CR, LF and CRLF sequences should be recognized ) */
#define PCRE_UCP 0x20000000 /* Change the way PCRE processes \B, \b, \D, \d, \S, \s, \W, \w etc. to use Unicode properties */
/**
* Regex expression error codes.
* This can be used with regex_compile_ex and regex_match_ex.
*/
enum /*RegexError*/
{
REGEX_ERROR_NONE = 0, /* No error */
REGEX_ERROR_NOMATCH = -1, /* No match was found */
REGEX_ERROR_NULL = -2,
REGEX_ERROR_BADOPTION = -3,
REGEX_ERROR_BADMAGIC = -4,
REGEX_ERROR_UNKNOWN_OPCODE = -5,
REGEX_ERROR_NOMEMORY = -6,
REGEX_ERROR_NOSUBSTRING = -7,
REGEX_ERROR_MATCHLIMIT = -8,
REGEX_ERROR_CALLOUT = -9, /* Never used by PCRE itself */
REGEX_ERROR_BADUTF8 = -10,
REGEX_ERROR_BADUTF8_OFFSET = -11,
REGEX_ERROR_PARTIAL = -12,
REGEX_ERROR_BADPARTIAL = -13,
REGEX_ERROR_INTERNAL = -14,
REGEX_ERROR_BADCOUNT = -15,
REGEX_ERROR_DFA_UITEM = -16,
REGEX_ERROR_DFA_UCOND = -17,
REGEX_ERROR_DFA_UMLIMIT = -18,
REGEX_ERROR_DFA_WSSIZE = -19,
REGEX_ERROR_DFA_RECURSE = -20,
REGEX_ERROR_RECURSIONLIMIT = -21,
REGEX_ERROR_NULLWSLIMIT = -22, /* No longer actually used */
REGEX_ERROR_BADNEWLINE = -23,
REGEX_ERROR_BADOFFSET = -24,
REGEX_ERROR_SHORTUTF8 = -25,
REGEX_ERROR_RECURSELOOP = -26,
REGEX_ERROR_JIT_STACKLIMIT = -27,
REGEX_ERROR_BADMODE = -28,
REGEX_ERROR_BADENDIANNESS = -29,
REGEX_ERROR_DFA_BADRESTART = -30,
REGEX_ERROR_JIT_BADOPTION = -31,
REGEX_ERROR_BADLENGTH = -32,
REGEX_ERROR_UNSET = -33
};
/**
* Precompile a regular expression.
*
* @note Use this if you intend on using the same expression multiple times.
* Pass the regex handle returned here to regex_match_c to check for matches.
*
* @note This handle is automatically freed on map change. However,
* if you are completely done with it before then, you should
* call regex_free on this handle.
*
* @note Consider using regex_compile_ex instead if you want to use PCRE_* flags.
*
* @param pattern The regular expression pattern.
* @param ret Error code encountered, if applicable.
* @param error Error message encountered, if applicable.
* @param maxLen Maximum string length of the error buffer.
* @param flags General flags for the regular expression.
* i = Ignore case
* m = Multilines (affects ^ and $ so that they match
* the start/end of a line rather than matching the
* start/end of the string).
* s = Single line (affects . so that it matches any character,
* even new line characters).
* x = Pattern extension (ignore whitespace and # comments).
*
* @return -1 on error in the pattern, > valid regex handle (> 0) on success.
*/
native Regex:regex_compile(const pattern[], &ret = 0, error[] = "", maxLen = 0, const flags[]="");
/**
* Matches a string against a pre-compiled regular expression pattern.
*
* @note You should free the returned handle with regex_free()
* when you are done with this pattern.
*
* @param pattern The regular expression pattern.
* @param string The string to check.
* @param ret Error code, if applicable, or number of results on success.
* @note Use the regex handle passed to this function to extract
* matches with regex_substr().
*
* @return -2 = Matching error (error code is stored in ret)
* 0 = No match.
* >1 = Number of results.
* @param string The string to check.
* @param pattern The regular expression pattern.
* @param ret Error code, if applicable, or number of results on success. See REGEX_ERROR_* defines.
*
* @note You should free the returned handle (with regex_free())
* when you are done with this pattern.
*
* @note Use the regex handle passed to this function to extract
* matches with regex_substr().
* @return -2 = Matching error (error code is stored in ret)
* 0 = No match.
* >1 = Number of results.
*/
native regex_match_c(const string[], Regex:pattern, &ret);
native regex_match_c(const string[], Regex:pattern, &ret = 0);
/**
* Matches a string against a regular expression pattern.
*
* @note If you intend on using the same regular expression pattern
* multiple times, consider using regex_compile and regex_match_c
* instead of making this function reparse the expression each time.
* @note If you intend on using the same regular expression pattern
* multiple times, consider using regex_compile and regex_match_ex
* instead of making this function reparse the expression each time.
*
* @param string The string to check.
* @param pattern The regular expression pattern.
* @param ret Error code, or result state of the match.
* @param error Error message, if applicable.
* @param maxLen Maximum length of the error buffer.
* @param flags General flags for the regular expression.
* i = Ignore case
* m = Multilines (affects ^ and $ so that they match
* the start/end of a line rather than matching the
* start/end of the string).
* s = Single line (affects . so that it matches any character,
* even new line characters).
* x = Pattern extension (ignore whitespace and # comments).
* @note Flags only exist in amxmodx 1.8 and later.
*
* @return -2 = Matching error (error code is stored in ret)
* -1 = Error in pattern (error message and offset # in error and ret)
* 0 = No match.
* >1 = Handle for getting more information (via regex_substr)
* @note You should free the returned handle with regex_free()
* when you are done extracting all of the substrings.
*
* @note Flags only exist in amxmodx 1.8 and later.
* @note You should free the returned handle (with regex_free())
* when you are done extracting all of the substrings.
* @param string The string to check.
* @param pattern The regular expression pattern.
* @param ret Error code, or result state of the match.
* @param error Error message, if applicable.
* @param maxLen Maximum length of the error buffer.
* @param flags General flags for the regular expression.
* i = Ignore case
* m = Multilines (affects ^ and $ so that they match
* the start/end of a line rather than matching the
* start/end of the string).
* s = Single line (affects . so that it matches any character,
* even new line characters).
* x = Pattern extension (ignore whitespace and # comments).
*
* @return -2 = Matching error (error code is stored in ret)
* -1 = Error in pattern (error message and offset # in error and ret)
* 0 = No match.
* >1 = Handle for getting more information (via regex_substr)
*/
native Regex:regex_match(const string[], const pattern[], &ret, error[], maxLen, const flags[] = "");
native Regex:regex_match(const string[], const pattern[], &ret = 0, error[] = "", maxLen = 0, const flags[] = "");
/**
* Returns a matched substring from a regex handle.
* Substring ids start at 0 and end at ret-1, where ret is from the corresponding
* regex_match or regex_match_c function call.
*
* @param id The regex handle to extract data from.
* @param str_id The index of the expression to get - starts at 0, and ends at ret - 1.
* @param buffer The buffer to set to the matching substring.
* @param maxLen The maximum string length of the buffer.
* @note Substring ids start at 0 and end at ret - 1, where ret is from the corresponding
* regex_match* function call.
*
* @param id The regex handle to extract data from.
* @param str_id The index of the expression to get - starts at 0, and ends at ret - 1.
* @param buffer The buffer to set to the matching substring.
* @param maxLen The maximum string length of the buffer.
*
* @return 1 on success, otherwise 0 on failure.
*/
native regex_substr(Regex:id, str_id, buffer[], maxLen);
/**
* Frees the memory associated with a regex result, and sets the handle to 0.
* This must be called on all results from regex_match() when you are done extracting
* the results with regex_substr().
* The results of regex_compile() (and subsequently, regex_match_c()) only need to be freed
* when you are done using the pattern.
*
* @note This must be called on all results from regex_match() when you are done extracting
* the results with regex_substr().
*
* @param id The regex handle to free.
* @note The results of regex_compile() or regex_compile_ex() (and subsequently, regex_match_c())
* only need to be freed when you are done using the pattern.
*
* @note Do not use the handle again after freeing it!
*
* @param id The regex handle to free.
* @noreturn
*
* @note Do not use the handle again after freeing it!
*/
*/
native regex_free(&Regex:id);
/**
* The following natives are only available in 1.8.3 and above.
*/
/**
* Precompile a regular expression.
*
* @note Use this if you intend on using the same expression multiple times.
* Pass the regex handle returned here to regex_match_c() to check for matches.
*
* @note Unlike regex_compile(), this allows you to use PCRE flags directly.
*
* @param pattern The regular expression pattern.
* @param flags General flags for the regular expression, see PCRE_* defines.
* @param error Error message encountered, if applicable.
* @param maxLen Maximum string length of the error buffer.
* @param errcode Regex type error code encountered, if applicable. See REGEX_ERROR_* defines.
*
* @return Valid regex handle (> 0) on success, or -1 on failure.
*/
native Regex:regex_compile_ex(const pattern[], flags = 0, error[]= "", maxLen = 0, &errcode = 0);
/**
* Matches a string against a pre-compiled regular expression pattern, matching all
* occurrences of the pattern inside the string. This is similar to using the "g" flag
* in perl regex.
*
* @note You should free the returned handle (with regex_free())
* when you are done with this pattern.
*
* @note Use the regex handle passed to this function to extract
* matches with regex_substr().
*
* @param pattern The regular expression pattern.
* @param string The string to check.
* @param ret Error code, if applicable, or number of results on success.
* See REGEX_ERROR_* defines.
*
* @return -2 = Matching error (error code is stored in ret)
* 0 = No match.
* >1 = Number of results.
*/
native regex_match_all_c(const string[], Regex:pattern, &ret = 0);
/**
* Matches a string against a regular expression pattern, matching all occurrences of the
* pattern inside the string. This is similar to using the "g" flag in perl regex.
*
* @note If you intend on using the same regular expression pattern
* multiple times, consider using regex_compile and regex_match_ex
* instead of making this function reparse the expression each time.
*
* @note Flags only exist in amxmodx 1.8 and later.
*
* @note You should free the returned handle with regex_free()
* when you are done extracting all of the substrings.
*
* @param string The string to check.
* @param pattern The regular expression pattern.
* @param flags General flags for the regular expression, see PCRE_* defines.
* @param error Error message encountered, if applicable.
* @param maxLen Maximum string length of the error buffer.
* @param errcode Regex type error code encountered, if applicable. See REGEX_ERROR_* defines.
*
* @return -2 = Matching error (error code is stored in ret)
* -1 = Error in pattern (error message and offset # in error and ret)
* 0 = No match.
* >1 = Handle for getting more information (via regex_substr)
*/
native Regex:regex_match_all(const string[], const pattern[], flags = 0, error[]= "", maxLen = 0, &errcode = 0);
/**
* Matches a string against a regular expression pattern.
*
* @note If you intend on using the same regular expression pattern
* multiple times, consider using compile regex_compile_ex and regex_match*
* instead of making this function reparse the expression each time.
*
* @param str The string to check.
* @param pattern The regular expression pattern.
* @param flags General flags for the regular expression.
* @param error Error message, if applicable.
* @param maxLen Maximum length of the error buffer.
* @param errcode Regex type error code encountered, if applicable. See REGEX_ERROR_* defines.
*
* @return -2 = Matching error (error code is stored in ret)
* -1 = Pattern error (error code is stored in ret)
* 0 = No match.
* >1 = Number of results.
*/
stock regex_match_simple(const str[], const pattern[], flags = 0, error[]= "", maxLen = 0, &errcode = 0)
{
new Regex:regex = regex_compile_ex(pattern, flags, error, maxLen, errcode);
if (regex < 0)
{
return -1;
}
new substrings = regex_match_c(regex, str);
regex_free(regex);
return substrings;
}
/**
* Flags used with regex_replace to control the replacement behavior.
*/
#define REGEX_FORMAT_DEFAULT 0 /* Uses the standard formatting rules to replace matches */
#define REGEX_FORMAT_NOCOPY (1<<0) /* The sections that do not match the regular expression are not copied when replacing matches. */
#define REGEX_FORMAT_FIRSTONLY (1<<1) /* Only the first occurrence of a regular expression is replaced. */
/**
* Perform a regular expression search and replace.
*
* An optional parameter, flags, allows you to specify options on how the replacement is performed.
* Supported format specifiers for replace parameter:
* $number : Substitutes the substring matched by group number.
* n must be an integer value designating a valid backreference, greater than 0, and of two digits at most.
* ${name} : Substitutes the substring matched by the named group name (a maximum of 32 characters).
* $& : Substitutes a copy of the whole match.
* $` : Substitutes all the text of the input string before the match.
* $' : Substitutes all the text of the input string after the match.
* $+ : Substitutes the last group that was captured.
* $_ : Substitutes the entire input string.
* $$ : Substitutes a literal "$".
* As note, the character \ can be also used with format specifier, this is same hehavior as $.
*
* @param pattern The regular expression pattern.
* @param string The string to check.
* @param error Error message, if applicable.
* @param maxLen Maximum length of the error buffer.
* @param replace The string will be used to replace any matches. See above for format specifiers.
* @param flags General flags to control how the string is replaced. See REGEX_FORMAT_* defines.
* @param errcode Regex type error code encountered, if applicable. See REGEX_ERROR_* defines.
*
* @return -2 = Matching error (error code is stored in ret)
* 0 = No match.
* >1 = Number of matches.
*/
native regex_replace(Regex:pattern, string[], maxLen, const replace[], flags = REGEX_FORMAT_DEFAULT, &errcode = 0);

View File

@ -0,0 +1,451 @@
#include <amxmodx>
#include <regex>
/**
* Warning: To get expected result, file encoding must be UTF-8 without BOM.
*/
public plugin_init()
{
register_plugin("Regex Test", AMXX_VERSION_STR, "AMXX Dev Team");
register_srvcmd("regex_test", "OnServerCommand");
}
new FailedCount;
new PassedCount;
test(const regex[], const replace[], const string[], const expectedString[], expectedCount = -1, regexFlags = 0, formatFlags = 0, bufferlen = -1)
{
new errorCode, error[128];
new Regex:r = regex_compile_ex(regex, regexFlags, error, charsmax(error), errorCode);
if (r == REGEX_PATTERN_FAIL || errorCode)
{
server_print("^t^t#%d. Pattern fail : ^"%s^"(%d)", ++FailedCount + PassedCount, error, errorCode);
}
else
{
new buffer[512];
copy(buffer, charsmax(buffer), string);
new errorCode;
new count = regex_replace(r, buffer, bufferlen != -1 ? bufferlen : charsmax(buffer), replace, formatFlags, errorCode);
if (expectedCount != -1 && count != expectedCount)
{
server_print("^t^t#%d. Failed - count = %d, expected count = %d", ++FailedCount + PassedCount, count, expectedCount);
}
else if (!equal(buffer, expectedString))
{
server_print("^t^t#%d. Failed - output = %s, expected output = %s", ++FailedCount + PassedCount, buffer, expectedString);
}
else
{
++PassedCount;
}
regex_free(r);
}
}
end()
{
server_print("Tests successful: %d/%d", PassedCount, PassedCount + FailedCount);
}
public OnServerCommand()
{
server_print("Testing regex_replace()");
server_print("^tChecking count...");
{
test( .regex = "(([0-9a-z]+)-([0-9]+))-(([0-9]+)-([0-9]+))",
.replace = "xxxx",
.string = "1-2-3-4 a-2-3-4 1-a-3-4 1-2-a-4 1-2-3-a a-a-a-a 4-3-2-1 100-200-300-400-500-600-700-800",
.expectedString = "xxxx xxxx 1-a-3-4 1-2-a-4 1-2-3-a a-a-a-a xxxx xxxx-xxxx",
.expectedCount = 5
);
test( .regex = "([a-z]+)",
.replace = "xxxx",
.string = "Here must only number like 42 and 13 appear",
.expectedString = "Hxxxx xxxx xxxx xxxx xxxx 42 xxxx 13 xxxx",
.expectedCount = 7
);
test( .regex = "((V(I|1)(4|A)GR(4|A))|(V(I|1)C(0|O)D(I|1)(N|\/\\\/)))", .regexFlags = PCRE_CASELESS,
.replace = "...",
.string = "Viagra V14GR4 Vicodin V1C0D1/\/ v1c0d1/|/",
.expectedString = "... ... ... ... v1c0d1/|/",
.expectedCount = 4
);
test( .regex = "\[(right)\](((?R)|[^^[]+?|\[)*)\[/\\1\]", .regexFlags = PCRE_CASELESS | PCRE_UNGREEDY,
.replace = "",
.string = "[CODE]&lt;td align=&quot;$stylevar[right]&quot;&gt;[/CODE]",
.expectedString = "[CODE]&lt;td align=&quot;$stylevar[right]&quot;&gt;[/CODE]",
.expectedCount = 0
);
test( .regex = "- This is a string$",
.replace = "This shouldn\'t work",
.string = "123456789 - Hello, world - This is a string.",
.expectedString = "123456789 - Hello, world - This is a string.",
.expectedCount = 0
);
test( .regex = "[0-35-9]",
.replace = "4",
.string = "123456789 - Hello, world - This is a string.",
.expectedString = "444444444 - Hello, world - This is a string.",
.expectedCount = 8
);
test( .regex = "\b[hH]\w{2,4}",
.replace = "Bonjour",
.string = "123456789 - Hello, world - This is a string.",
.expectedString = "123456789 - Bonjour, world - This is a string.",
.expectedCount = 1
);
test( .regex = "(\w)\s*-\s*(\w)",
.replace = "$1. $2",
.string = "123456789 - Hello, world - This is a string.",
.expectedString = "123456789. Hello, world. This is a string.",
.expectedCount = 2
);
test( .regex = "([a-z]\w+)@(\w+)\.(\w+)\.([a-z]{2,})",
.replace = "$1 at $2 dot $3 dot $4",
.string = "josmessa@uk.ibm.com",
.expectedString = "josmessa at uk dot ibm dot com",
.expectedCount = 1
);
test( .regex = "\b\w{1}s",
.replace = "test",
.string = "This is a string. (0-9) as well as parentheses",
.expectedString = "This test a string. (0-9) test well test parentheses",
.expectedCount = 3
);
test( .regex = "(\d{1})-(\d{1})",
.replace = "$1 to $2",
.string = "This is a string. It contains numbers (0-9) as well as parentheses and some other things!",
.expectedString = "This is a string. It contains numbers (0 to 9) as well as parentheses and some other things!",
.expectedCount = 1
);
test( .regex = "[\(!\)]",
.replace = "*",
.string = "This is a string. It contains numbers (0-9) as well as parentheses and some other things!",
.expectedString = "This is a string. It contains numbers *0-9* as well as parentheses and some other things*",
.expectedCount = 3
);
}
server_print("^tChecking edges cases...");
{
test(.regex = "[0-9]+", .replace = "*", .string = "", .expectedString = "", .expectedCount = 0);
test(.regex = "([0-9]+)", .replace = "", .string = "123", .expectedString = "", .expectedCount = 1);
test(.regex = "a", .replace = "\", .string = "a", .expectedString = "\", .expectedCount = 1);
test(.regex = "^^", .replace = "x", .string = "a", .expectedString = "xa", .expectedCount = 1);
test(.regex = "b", .replace = "\", .string = "b", .expectedString = "\", .expectedCount = 1, .bufferlen = 1);
test(.regex = "b", .replace = "^^", .string = "b", .expectedString = "b", .expectedCount = 0, .bufferlen = 0);
test(.regex = "\w+", .replace = "123", .string = "abc", .expectedString = "12", .expectedCount = 1, .bufferlen = 2);
}
server_print("^tChecking UTF-8 support...");
{
test(.regex = "(\w+)", .replace = "*", .string = "éà@É", .expectedString = "éà@É", .expectedCount = 0);
test(.regex = "(\w+)", .replace = "*", .string = "éà@É", .expectedString = "*@*", .expectedCount = 2, .regexFlags = PCRE_UCP | PCRE_UTF8);
test(.regex = "(\w+)", .replace = "字", .string = "éà@É", .expectedString = "字@字",.expectedCount = 2, .regexFlags = PCRE_UCP | PCRE_UTF8);
test(.regex = "(\w+)", .replace = "字", .string = "éà@É", .expectedString = "字", .expectedCount = 2, .regexFlags = PCRE_UCP | PCRE_UTF8, .bufferlen = 3);
}
server_print("^tChecking substitutions...");
{
test(.regex = "x", .replace = "y", .string = "text", .expectedString = "teyt" );
test(.regex = "x", .replace = "$", .string = "text", .expectedString = "te$t" );
test(.regex = "x", .replace = "$1", .string = "text", .expectedString = "te$1t" );
test(.regex = "x", .replace = "${1", .string = "text", .expectedString = "te${1t" );
test(.regex = "x", .replace = "${", .string = "text", .expectedString = "te${t" );
test(.regex = "x", .replace = "${$0", .string = "text", .expectedString = "te${xt" );
test(.regex = "x", .replace = "${1}", .string = "text", .expectedString = "te${1}t" );
test(.regex = "x", .replace = "${1}", .string = "text", .expectedString = "te${1}t" );
test(.regex = "x", .replace = "$5", .string = "text", .expectedString = "te$5t" );
test(.regex = "x", .replace = "$5", .string = "te(x)t", .expectedString = "te($5)t" );
test(.regex = "x", .replace = "${foo", .string = "text", .expectedString = "te${foot" );
test(.regex = "(x)", .replace = "$5", .string = "text", .expectedString = "te$5t" );
test(.regex = "(x)", .replace = "$1", .string = "text", .expectedString = "text" );
test(.regex = "e(x)", .replace = "$1", .string = "text", .expectedString = "txt" );
test(.regex = "e(x)", .replace = "$5", .string = "text", .expectedString = "t$5t" );
test(.regex = "e(x)", .replace = "$4", .string = "text", .expectedString = "t$4t" );
test(.regex = "e(x)", .replace = "$3", .string = "text", .expectedString = "t$3t" );
test(.regex = "e(x)", .replace = "${1}", .string = "text", .expectedString = "txt" );
test(.regex = "e(x)", .replace = "${3}", .string = "text", .expectedString = "t${3}t" );
test(.regex = "e(x)", .replace = "${1}${3}", .string = "text", .expectedString = "tx${3}t" );
test(.regex = "e(x)", .replace = "${1}${name}", .string = "text", .expectedString = "tx${name}t");
test(.regex = "e(?<foo>x)", .replace = "${1}${name}", .string = "text", .expectedString = "tx${name}t");
test(.regex = "e(?<foo>x)", .replace = "${1}${foo}", .string = "text", .expectedString = "txxt" );
test(.regex = "e(?<foo>x)", .replace = "${goll}${foo}", .string = "text", .expectedString = "t${goll}xt");
test(.regex = "e(?<foo>x)", .replace = "${goll${foo}", .string = "text", .expectedString = "t${gollxt" );
test(.regex = "e(?<foo>x)", .replace = "${goll${foo}}", .string = "text", .expectedString = "t${gollx}t");
test(.regex = "e(?<foo>x)", .replace = "$${foo}}", .string = "text", .expectedString = "t${foo}}t" );
test(.regex = "e(?<foo>x)", .replace = "${${foo}}", .string = "text", .expectedString = "t${x}t" );
test(.regex = "e(?<foo>x)", .replace = "$${foo}}", .string = "text", .expectedString = "t${foo}}t" );
test(.regex = "e(?<foo>x)", .replace = "$${bfoo}}", .string = "text", .expectedString = "t${bfoo}}t");
test(.regex = "e(?<foo>x)", .replace = "$${foo}}", .string = "text", .expectedString = "t${foo}}t" );
test(.regex = "e(?<foo>x)", .replace = "$${foo}", .string = "text", .expectedString = "t${foo}t" );
test(.regex = "e(?<foo>x)", .replace = "$$", .string = "text", .expectedString = "t$t" );
test(.regex = "(e)(?<foo>x)", .replace = "${foo}$1$2", .string = "text", .expectedString = "txext" );
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2", .string = "text", .expectedString = "teext" );
test(.regex = "(e)(?<foo>x)", .replace = "${foo}$1$2$+", .string = "text", .expectedString = "txexxt" );
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2$+", .string = "text", .expectedString = "teexxt" );
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2$_", .string = "texts", .expectedString = "teextextsts");
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2$`", .string = "texts", .expectedString = "teextts" ),
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2$'", .string = "texts", .expectedString = "teextsts" ),
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2$&", .string = "texts", .expectedString = "teexexts" ),
test(.regex = "x", .replace = "y", .string = "text", .expectedString = "teyt" );
test(.regex = "x", .replace = "$", .string = "text", .expectedString = "te$t" );
test(.regex = "x", .replace = "$1", .string = "text", .expectedString = "te$1t" );
test(.regex = "x", .replace = "${1}", .string = "text", .expectedString = "te${1}t" );
test(.regex = "x", .replace = "$5", .string = "text", .expectedString = "te$5t" );
test(.regex = "x", .replace = "$5", .string = "te(x)t", .expectedString = "te($5)t" );
test(.regex = "x", .replace = "${foo", .string = "text", .expectedString = "te${foot" );
test(.regex = "(x)", .replace = "$5", .string = "text", .expectedString = "te$5t" );
test(.regex = "(x)", .replace = "$1", .string = "text", .expectedString = "text" );
test(.regex = "e(x)", .replace = "$1", .string = "text", .expectedString = "txt" );
test(.regex = "e(x)", .replace = "$5", .string = "text", .expectedString = "t$5t" );
test(.regex = "e(x)", .replace = "$4", .string = "text", .expectedString = "t$4t" );
test(.regex = "e(x)", .replace = "$3", .string = "text", .expectedString = "t$3t" );
test(.regex = "e(x)", .replace = "${1}", .string = "text", .expectedString = "txt" );
test(.regex = "e(x)", .replace = "${3}", .string = "text", .expectedString = "t${3}t" );
test(.regex = "e(x)", .replace = "${1}${3}", .string = "text", .expectedString = "tx${3}t" );
test(.regex = "e(x)", .replace = "${1}${name}", .string = "text", .expectedString = "tx${name}t");
test(.regex = "e(?<foo>x)", .replace = "${1}${name}", .string = "text", .expectedString = "tx${name}t");
test(.regex = "e(?<foo>x)", .replace = "${1}${foo}", .string = "text", .expectedString = "txxt" );
test(.regex = "e(?<foo>x)", .replace = "${goll}${foo}", .string = "text", .expectedString = "t${goll}xt");
test(.regex = "e(?<foo>x)", .replace = "${goll${foo}", .string = "text", .expectedString = "t${gollxt" );
test(.regex = "e(?<foo>x)", .replace = "${goll${foo}}", .string = "text", .expectedString = "t${gollx}t");
test(.regex = "e(?<foo>x)", .replace = "$${foo}}", .string = "text", .expectedString = "t${foo}}t" );
test(.regex = "e(?<foo>x)", .replace = "${${foo}}", .string = "text", .expectedString = "t${x}t" );
test(.regex = "e(?<foo>x)", .replace = "$${foo}}", .string = "text", .expectedString = "t${foo}}t" );
test(.regex = "e(?<foo>x)", .replace = "$${bfoo}}", .string = "text", .expectedString = "t${bfoo}}t");
test(.regex = "e(?<foo>x)", .replace = "$${foo}}", .string = "text", .expectedString = "t${foo}}t" );
test(.regex = "e(?<foo>x)", .replace = "$${foo}", .string = "text", .expectedString = "t${foo}t" );
test(.regex = "e(?<foo>x)", .replace = "$$", .string = "text", .expectedString = "t$t" );
test(.regex = "(e)(?<foo>x)", .replace = "${foo}$1$2", .string = "text", .expectedString = "txext" );
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2", .string = "text", .expectedString = "teext" );
test(.regex = "(e)(?<foo>x)", .replace = "${foo}$1$2$+", .string = "text", .expectedString = "txexxt" );
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2$+", .string = "text", .expectedString = "teexxt" );
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2$_", .string = "texts", .expectedString = "teextextsts");
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2$`", .string = "texts", .expectedString = "teextts" );
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2$'", .string = "texts", .expectedString = "teextsts" );
test(.regex = "(?<foo>e)(x)", .replace = "${foo}$1$2$&", .string = "texts", .expectedString = "teexexts" );
test(.regex = "<(.+?)>", .replace = "[$0:$1]", .string = "<i>am not</i>", .expectedString = "[<i>:i]am not[</i>:/i]");
test(.regex = "(?<foo>e)(?<foo>x)", .replace = "${foo}$1$2", .string = "text", .expectedString = "teext", .regexFlags = PCRE_DUPNAMES);
test(.regex = "\b(\w+)(\s)(\w+)\b", .replace = "$3$2$1", .string = "one two", .expectedString = "two one");
test(.regex = "\b(\d+)\s?USD", .replace = "$$$1", .string = "103 USD", .expectedString = "$103" );
test(.regex = "\b(?<w1>\w+)(\s)(?<w2>\w+)\b", .replace = "${w2} ${w1}", .string = "one two", .expectedString = "two one");
test(.regex = "(\$*(\d*(\.+\d+)?){1})", .replace = "**$&", .string = "$1.30", .expectedString = "**$1.30**");
test(.regex = "B+", .replace = "$`", .string = "AABBCC", .expectedString = "AAAACC");
test(.regex = "B+", .replace = "$'", .string = "AABBCC", .expectedString = "AACCCC");
test(.regex = "B+(C+)", .replace = "$+", .string = "AABBCCDD", .expectedString = "AACCDD");
test(.regex = "B+", .replace = "$_", .string = "AABBCC", .expectedString = "AAAABBCCCC");
test(.regex = "(F)(2)(3)(4)(5)(6)(7)(8)(9)(10)(L)\11", .replace = "${S}$11$1", .string = "F2345678910L71", .expectedString = "F2345678910L71"),
test(.regex = "(F)(2)(3)(4)(5)(6)(7)(8)(9)(10)(L)\11", .replace = "${S}$11$1", .string = "F2345678910LL1", .expectedString = "${S}LF1");
}
server_print("^tChecking moar #1...");
{
test(.string = "(?(w)a|o)" , .regex = "\(\?\(\w+\).*\|?.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?(w)|o)" , .regex = "\(\?\(\w+\).*\|?.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?(w)a)" , .regex = "\(\?\(\w+\).*\|?.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?(w)a|)" , .regex = "\(\?\(\w+\).*\|?.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?(w)?|a|o)" , .regex = "\(\?\(\w+\).*\|?.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?(w)||o)" , .regex = "\(\?\(\w+\).*\|?.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?(w)(a)" , .regex = "\(\?\(\w+\).*\|?.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?(w))\a|)" , .regex = "\(\?\(\w+\).*\|?.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?(2)a|o)" , .regex = "\(\?\([^^\)]+\).*\|?.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?(|)a|o)" , .regex = "\(\?\([^^\)]+\).*\|?.*\)" , .replace = "r", .expectedString = "r");
test(.string = "a\3b" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\(\d+)" , .replace = "\5", .expectedString = "a\5b");
test(.string = "\3b" , .regex = "(?=(?:\A|[^^\\])(?:[\\]{2}){0,3})\\(\d+)" , .replace = "\5", .expectedString = "\5b");
test(.string = "\\\3b" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\(\d+)" , .replace = "\5", .expectedString = "\\\5b");
test(.string = "\\\k<g>" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\k<(\w+)>" , .replace = "\5", .expectedString = "\\\5");
test(.string = "\\\\k'g'" , .regex = "(?:(?:\A|[^^\\])(?:[\\]{2}){0,3})\\k'(\w+)'" , .replace = "\5", .expectedString = "\\\\k'g'");
test(.string = "a\\\\k'g'" , .regex = "(?:(?:\A|[^^\\])(?:[\\]{2}){0,3})\\k'(\w+)'" , .replace = "\5", .expectedString = "a\\\\k'g'");
test(.string = "\k'g'" , .regex = "(?:(?:\A|[^^\\])(?:[\\]{2}){0,3})\\k'(\w+)'" , .replace = "\5", .expectedString = "\5");
test(.string = "(?<n1-n2>)" , .regex = "\(\?<[A-Za-z]\w*-[A-Za-z]\w*>.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?'n1-n2'a)" , .regex = "\(\?'[A-Za-z]\w*-[A-Za-z]\w*'.*\)" , .replace = "r", .expectedString = "r");
test(.string = "\p{Isa}" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3}\\[pP]\{)Is(?=\w+\})", .replace = "In", .expectedString = "\p{Ina}");
test(.string = "\p{Is}" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3}\\[pP]\{)Is(?=\w+\})", .replace = "In", .expectedString = "\p{Is}");
test(.string = "\p{Isa" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3}\\[pP]\{)Is(?=\w+\})", .replace = "In", .expectedString = "\p{Isa");
test(.string = "a(?#|)" , .regex = "\(\?#[^^\)]*\)" , .replace = "", .expectedString = "a");
test(.string = "(?#|)" , .regex = "\(\?#[^^\)]*\)" , .replace = "", .expectedString = "");
test(.string = "(?#|)" , .regex = "\#[^^\n\r]*" , .replace = "", .expectedString = "(?");
test(.string = "(?inm-xs:\#)" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3}\()\?[imsx]*n[-imsx]*:[^^\)]+\)", .replace = "r", .expectedString = "(r");
test(.string = "(?ni:())" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3}\()\?[imsx]*n[-imsx]*:[^^\)]+\)", .replace = "r", .expectedString = "(r)");
test(.string = "(?x-i:)" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3}\()\?[imsx]*n[-imsx]*:[^^\)]+\)", .replace = "r", .expectedString = "(?x-i:)");
test(.string = "(?n:))" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3}\()\?[imsx]*n[-imsx]*:[^^\)]+\)", .replace = "r", .expectedString = "(?n:))");
test(.string = "(?<n1>)" , .regex = "\(\?<[A-Za-z]\w*>.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?'n1'y)" , .regex = "\(\?'[A-Za-z]\w*'.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?<45>y)" , .regex = "\(\?<\d+>.*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?'7'o)" , .regex = "\(\?'\d+'.*\)" , .replace = "r", .expectedString = "r");
test(.string = "\\\(" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\\(" , .replace = "r", .expectedString = "\\r");
test(.string = "a\\\(" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\\(" , .replace = "r", .expectedString = "a\\r");
test(.string = "\\(" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\\(" , .replace = "r", .expectedString = "\r");
test(.string = "a\\(" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\\(" , .replace = "r", .expectedString = "a\r");
test(.string = "\(" , .regex = "(?:(?:\A|[^^\\])(?:[\\]{2}){0,3})\\\(" , .replace = "r", .expectedString = "r");
test(.string = "a\(" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\\(" , .replace = "r", .expectedString = "ar");
test(.string = "?:" , .regex = "(?:^^\?[:imnsx=!>-]|^^\?<[!=])" , .replace = "r", .expectedString = "r");
test(.string = "?<!" , .regex = "(?:^^\?[:imnsx=!>-]|^^\?<[!=])" , .replace = "r", .expectedString = "r");
test(.string = "?-" , .regex = "(?:^^\?[:imnsx=!>-]|^^\?<[!=])" , .replace = "r", .expectedString = "r");
test(.string = "\(?<n>" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3}\()\?<[A-Za-z]\w*>", .replace = "r", .expectedString = "\(r");
test(.string = "a\(?'n'" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3}\()\?'[A-Za-z]\w*'", .replace = "r", .expectedString = "a\(r");
test(.string = "\\(?<2>" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3}\()\?<\d+>" , .replace = "r", .expectedString = "\\(r");
test(.string = "(?'2'" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3}\()\?'\d+'" , .replace = "r", .expectedString = "(r");
test(.string = "\[\b]" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2})*(?:\[|\[[^^\[\]]*[^^\[\]\\])(?:[\\]{2})*)\\b(?=[^^\[\]]*\])", .replace = "\\u8", .expectedString = "\[\u8]");
test(.string = "\[a\bb]" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2})*(?:\[|\[[^^\[\]]*[^^\[\]\\])(?:[\\]{2})*)\\b(?=[^^\[\]]*\])", .replace = "\\u8", .expectedString = "\[a\u8b]");
test(.string = "\[\b]" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2})*(?:\[|\[[^^\[\]]*[^^\[\]\\])(?:[\\]{2})*)\\b(?=[^^\[\]]*\])", .replace = "\\u8", .expectedString = "\[\u8]");
test(.string = "\[\b]" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2})*(?:\[|\[[^^\[\]]*[^^\[\]\\])(?:[\\]{2})*)\\b(?=[^^\[\]]*\])", .replace = "\\u8", .expectedString = "\[\u8]");
test(.string = "\[\\b]" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2})*(?:\[|\[[^^\[\]]*[^^\[\]\\])(?:[\\]{2})*)\\b(?=[^^\[\]]*\])", .replace = "\\u8", .expectedString = "\[\\u8]");
test(.string = "[[]" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2})*(?:\[|\[[^^\[\]]*[^^\[\]\\])(?:[\\]{2})*)\[(?=[^^\[\]]*\])" , .replace = "\\[" , .expectedString = "[\[]");
test(.string = "\[[]" , .regex = "(?:(?:\A|[^^\\])(?:[\\]{2})*(?:\[|\[[^^\[\]]*[^^\[\]\\])(?:[\\]{2})*)\[(?=[^^\[\]]*\])" , .replace = "\[" , .expectedString = "\[[]");
test(.string = "\[\[]" , .regex = "(?:(?:\A|[^^\\])(?:[\\]{2})*(?:\[|\[[^^\[\]]*[^^\[\]\\])(?:[\\]{2})*)\[(?=[^^\[\]]*\])" , .replace = "\[" , .expectedString = "\[\[]");
test(.string = "\[\[]" , .regex = "(?:(?:\A|[^^\\])(?:[\\]{2})*(?:\[|\[[^^\[\]]*[^^\[\]\\])(?:[\\]{2})*)\[(?=[^^\[\]]*\])" , .replace = "\[" , .expectedString = "\[\[]");
test(.string = "\{" , .regex = "(?=(?:\A|[^^\\])(?:[\\]{2})*)\{(?!\d\d*(,(\d\d*)?)?\})", .replace = "\{", .expectedString = "\\{");
test(.string = "\{" , .regex = "(?=(?:\A|[^^\\])(?:[\\]{2})*)\{(?!\d\d*(,(\d\d*)?)?\})", .replace = "\{", .expectedString = "\\{");
test(.string = "\{1,2}" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2})*)\{(?!\d\d*(,(\d\d*)?)?\})", .replace = "\{", .expectedString = "\{1,2}");
test(.string = "\{1}" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2})*)\{(?!\d\d*(,(\d\d*)?)?\})", .replace = "\{", .expectedString = "\{1}");
test(.string = "\{1,}" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2})*)\{(?!\d\d*(,(\d\d*)?)?\})", .replace = "\{", .expectedString = "\{1,}");
test(.string = "\{1" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2})*)\{(?!\d\d*(,(\d\d*)?)?\})", .replace = "\\{", .expectedString = "\{1");
test(.string = "\\(?!{1}" , .regex = "(\A|((\A|[^^\\])([\\]{2})*\((\?([:>=!]|<([=!]|(\w+>))))?))\{\d+(,(\d+)?)?\}", .replace = "\5", .expectedString = "?!");
test(.string = "{1}" , .regex = "(\A|((\A|[^^\\])([\\]{2})*\((\?([:>=!]|<([=!]|(\w+>))))?))\{\d+(,(\d+)?)?\}", .replace = "r", .expectedString = "r");
test(.string = "({1}" , .regex = "(\A|((\A|[^^\\])([\\]{2})*\((\?([:>=!]|<([=!]|(\w+>))))?))\{\d+(,(\d+)?)?\}", .replace = "r", .expectedString = "r");
test(.string = "(?{1}" , .regex = "(\A|((\A|[^^\\])([\\]{2})*\((\?([:>=!]|<([=!]|(\w+>))))?))\{\d+(,(\d+)?)?\}", .replace = "r", .expectedString = "(?{1}");
test(.string = "(?:{1}" , .regex = "(\A|((\A|[^^\\])([\\]{2})*\((\?([:>=!]|<([=!]|(\w+>))))?))\{\d+(,(\d+)?)?\}", .replace = "r", .expectedString = "r");
test(.string = "\({1}" , .regex = "(\A|((\A|[^^\\])([\\]{2})*\((\?([:>=!]|<([=!]|(\w+>))))?))\{\d+(,(\d+)?)?\}", .replace = "r", .expectedString = "\({1}");
test(.string = "\p{Isa}" , .regex = "(?!\\[pP]\{)Is(?=\w+\})" , .replace = "In", .expectedString = "\p{Ina}");
test(.string = "\p{Is}" , .regex = "(?!\\[pP]\{)Is(?=\w+\})" , .replace = "In", .expectedString = "\p{Is}");
test(.string = "\p{Isa" , .regex = "(?!\\[pP]\{)Is(?=\w+\})" , .replace = "In", .expectedString = "\p{Isa");
test(.string = "\}" , .regex = "(?!(\\A|[^^\\])(\\{2})*\\{\\d\\d*(,(\\d\\d*)?)?)\\}", .replace = "\\}", .expectedString = "\}");
test(.string = "{\}" , .regex = "(?!(\A|[^^\^^])(\^^{2})*\{\d\d*(,(\d\d*)?)?)\}", .replace = "\\}", .expectedString = "{\\}");
test(.string = "{1,2}" , .regex = "(?!(\A|[^^\\])(\\{2})*\{\d\d*(,(\d\d*)?)?)\}" , .replace = "\\}", .expectedString = "{1,2\}");
test(.string = "\{1}" , .regex = "(?!(\A|[^^\\])(\\{2})*\{\d\d*(,(\d\d*)?)?)\}" , .replace = "\\}", .expectedString = "\{1\}");
test(.string = "\{1\}" , .regex = "(?!(\A|[^^\\])(\\{2})*\{\d\d*(,(\d\d*)?)?)\}" , .replace = "\\}", .expectedString = "\{1\\}");
test(.string = "\{1}" , .regex = "(?!(\A|[^^\\])(\\{2})*\{\d\d*(,(\d\d*)?)?)\}" , .replace = "\\}", .expectedString = "\{1\}");
test(.string = "{1,}" , .regex = "(?!(\A|[^^\\])(\\{2})*\{\d\d*(,(\d\d*)?)?)\}" , .replace = "\\}", .expectedString = "{1,\}");
test(.string = "a(?<!b*c)" , .regex = "\(\?\<[=!][^^\)]*(?:[\*\+]|\{\d+,\}).*\)" , .replace = "r", .expectedString = "ar");
test(.string = "a(?<!b+c)" , .regex = "\(\?\<[=!][^^\)]*(?:[\*\+]|\{\d+,\}).*\)" , .replace = "r", .expectedString = "ar");
test(.string = "(?<!b{1}c))" , .regex = "\(\?\<[=!][^^\)]*(?:[\*\+]|\{\d+,\}).*\)" , .replace = "r", .expectedString = "(?<!b{1}c))");
test(.string = "(?<!b{1,}c)" , .regex = "\(\?\<[=!][^^\)]*(?:[\*\+]|\{\d+,\}).*\)" , .replace = "r", .expectedString = "r");
test(.string = "(?<!b{1,4}c)" , .regex = "\(\?\<[=!][^^\)]*(?:[\*\+]|\{\d+,\}).*\)" , .replace = "r", .expectedString = "(?<!b{1,4}c)");
test(.string = "a\3b" , .regex = "\\(\d+)" , .replace = "\5", .expectedString = "a\5b");
test(.string = "\3b" , .regex = "\\(\d+)" , .replace = "\5", .expectedString = "\5b");
test(.string = "\\3b" , .regex = "(?!\\\\)\\(\d)" , .replace = "\5", . expectedString = "\\5b");
test(.string = "a\\3b" , .regex = "(?:(\\){0,3})\\(\d)" , .replace = "\5", . expectedString = "a\5b");
test(.string = "\\k<g>" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\k<(\w)>" , .replace = "\5", .expectedString = "\\5");
test(.string = "a\\k<g>" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\k<(\w)>" , .replace = "\5", .expectedString = "a\\5");
test(.string = "\\k'g'" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\k'(\w)'" , .replace = "\5", .expectedString = "\\5");
test(.string = "a\\k'g'" , .regex = "(?!(?:\A|[^^\\])(?:[\\]{2}){0,3})\\k'(\w)'" , .replace = "\5", .expectedString = "a\\5");
test(.string = "\k'g'" , .regex = "(?:(?:\A|[^^\\])(?:[\\]{2}){0,3})\\k'(\w)'" , .replace = "\5", .expectedString = "\5");
}
server_print("^tChecking moar #2...");
{
test(.regex = "^^((?>[a-zA-Z\d!#$%&'*+\-\/=?^^_`{|}~]+\x20*|^"((?=[\x01-\x7f])[^^^"\\]|\\[\x01-\x7f])*^"\x20*)*(?<angle><))?((?!\.)(?>\.?[a-zA-Z\d!#$%&'*+\-\/=?^^_`{|}~]+)+|^"((?=[\x01-\x7f])[^^^"\\]|\\[\x01-\x7f])*^")@(((?!-)[a-zA-Z\d\-]+(?<!-)\.)+[a-zA-Z]{2,}|\[(((?(?<!\[)\.)(25[0-5]|2[0-4]\d|[01]?\d?\d)){4}|[a-zA-Z\d\-]*[a-zA-Z\d]:((?=[\x01-\x7f])[^^\\\[\]]|\\[\x01-\x7f])+)\])(?(angle)>)$" ,
.replace = "$1$4@$7net>",
.string = "Name Surname <name.surname@blah.com>",
.expectedString = "Name Surname <name.surname@blah.net>"
);
test(.regex = "([A-Z])\w+",
.replace = "*snip*",
.string = "Welcome to RegExr v2.0 by gskinner.com!\
\
Edit the Expression & Text to see matches. Roll over matches or the expression for details. Undo mistakes with ctrl-z. Save & Share expressions with friends or the Community. A full Reference & Help is available in the Library, or watch the video Tutorial.\
\
Sample text for testing:\
abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ\
:0123456789 +-.,!@#$%^^&*();\/|<>^"'\
12345 -98.7 3.141 .6180 9,000 +42\
555.123.4567 +1-(800)-555-2468\
foo@demo.net bar.ba@test.co.uk\
www.demo.com http://foo.co.uk/\
http://regexr.com/foo.html?q=bar",
.expectedString = "*snip* to *snip* v2.0 by gskinner.com!\
\
*snip* the *snip* & *snip* to see matches. *snip* over matches or the expression for details. *snip* mistakes with ctrl-z. *snip* & *snip* expressions with friends or the *snip*. A full *snip* & *snip* is available in the *snip*, or watch the video *snip*.\
\
*snip* text for testing:\
abcdefghijklmnopqrstuvwxyz *snip*\
:0123456789 +-.,!@#$%^^&*();\/|<>^"'\
12345 -98.7 3.141 .6180 9,000 +42\
555.123.4567 +1-(800)-555-2468\
foo@demo.net bar.ba@test.co.uk\
www.de",
.regexFlags = PCRE_EXTENDED
);
test(.regex = "/\*(?>[^^*/]+|\*[^^/]|/[^^*]|/\*(?>[^^*/]+|\*[^^/]|/[^^*])*\*/)*\*/",
.replace = "",
.string = "/* comment */\
no comment\
/* comment\
spanning\
multiple\
lines */\
/* comment /* nesting */ of /* two */ levels supported */\
/* comment /* nesting */ of /* /* more than */ two levels */ not supported */",
.expectedString = "no comment\
/* comment of not supported */"
);
test(.regex = "\b(?<protocol>https?|ftp)://(?<domain>[A-Z0-9.-]+)(?<file>/[A-Z0-9+&@#/%=~_|!:,.;-]*)?(?<parameters>\?[A-Z0-9+&@#/%=~_|!:,.;]*)?",
.replace = "${protocol}s://site.com${file}^n",
.string = "http://www.alliedmods.net http://www.alliedmods.net/ http://www.alliedmods.net/test.php http://www.alliedmods.net/index.php?secret=x Something interesting at http://www.alliedmods.net.",
.expectedString = "https://site.com^nhttps://site.com/^nhttps://site.com/test.php^nhttps://site.com/index.php^nhttps://site.com^n",
.regexFlags = PCRE_CASELESS | PCRE_EXTENDED,
.formatFlags = REGEX_FORMAT_NOCOPY
);
test(.regex = "\b(https?|ftp)://([A-Z0-9.-]+)(/[A-Z0-9+&@#/%=~_|!:,.;-]*)?(\?[A-Z0-9+&@#/%=~_|!:,.;]*)?",
.replace = "$1s://site.com$3^n",
.string = "http://www.alliedmods.net http://www.alliedmods.net/ http://www.alliedmods.net/test.php http://www.alliedmods.net/index.php?secret=x Something interesting at http://www.alliedmods.net.",
.expectedString = "https://site.com^nhttps://site.com/^nhttps://site.com/test.php^nhttps://site.com/index.php^nhttps://site.com^n",
.regexFlags = PCRE_CASELESS | PCRE_EXTENDED,
.formatFlags = REGEX_FORMAT_NOCOPY
);
test(.regex = "\b(https?|ftp)://([A-Z0-9.-]+)(/[A-Z0-9+&@#/%=~_|!:,.;-]*)?(\?[A-Z0-9+&@#/%=~_|!:,.;]*)?",
.replace = "$1s://site.com$3^n",
.string = "http://www.alliedmods.net http://www.alliedmods.net/ http://www.alliedmods.net/test.php http://www.alliedmods.net/index.php?secret=x Something interesting at http://www.alliedmods.net.",
.expectedString = "https://site.com^n",
.regexFlags = PCRE_CASELESS | PCRE_EXTENDED,
.formatFlags = REGEX_FORMAT_NOCOPY | REGEX_FORMAT_FIRSTONLY
);
test(.regex = "^^(.++)\r?\n(?=(?:^^(?!\1$).*+\r?\n)*+\1$)",
.replace = "",
.string = "one^n\
two^n\
three^n\
four^n\
two^n\
three^n\
four^n\
three^n\
four^n\
four",
.expectedString = "one^n\
two^n\
three^n\
four",
.regexFlags = PCRE_EXTENDED | PCRE_MULTILINE
);
}
end();
}