@ -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);
|
451
plugins/testsuite/regex_test.sma
Normal file
451
plugins/testsuite/regex_test.sma
Normal 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]<td align="$stylevar[right]">[/CODE]",
|
||||
.expectedString = "[CODE]<td align="$stylevar[right]">[/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();
|
||||
}
|
Reference in New Issue
Block a user