Index: include/zbxregexp.h
===================================================================
--- include/zbxregexp.h	(revision 86290)
+++ include/zbxregexp.h	(revision 86291)
@@ -38,6 +38,7 @@
 
 /* regular expressions */
 int	zbx_regexp_compile(const char *pattern, zbx_regexp_t **regexp, const char **error);
+int	zbx_regexp_compile_ext(const char *pattern, zbx_regexp_t **regexp, int flags, const char **error);
 void	zbx_regexp_free(zbx_regexp_t *regexp);
 int	zbx_regexp_match_precompiled(const char *string, const zbx_regexp_t *regexp);
 char	*zbx_regexp_match(const char *string, const char *pattern, int *len);
@@ -44,6 +45,8 @@
 int	zbx_regexp_sub(const char *string, const char *pattern, const char *output_template, char **out);
 int	zbx_mregexp_sub(const char *string, const char *pattern, const char *output_template, char **out);
 int	zbx_iregexp_sub(const char *string, const char *pattern, const char *output_template, char **out);
+int	zbx_regexp_msub_precompiled(const char *string, const zbx_regexp_t *regexp, const char *output_template,
+		char **out);
 
 void	zbx_regexp_clean_expressions(zbx_vector_ptr_t *expressions);
 
Index: src/zabbix_server/preprocessor/item_preproc.c
===================================================================
--- src/zabbix_server/preprocessor/item_preproc.c	(revision 86290)
+++ src/zabbix_server/preprocessor/item_preproc.c	(revision 86291)
@@ -743,7 +743,9 @@
  ******************************************************************************/
 static int	item_preproc_regsub_op(zbx_variant_t *value, const char *params, char **errmsg)
 {
-	char	pattern[ITEM_PREPROC_PARAMS_LEN * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1], *output, *new_value = NULL;
+	char		pattern[ITEM_PREPROC_PARAMS_LEN * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1], *output, *new_value = NULL;
+	const char	*regex_error;
+	zbx_regexp_t	*regex = NULL;
 
 	if (FAIL == item_preproc_convert_value(value, ZBX_VARIANT_STR, errmsg))
 		return FAIL;
@@ -757,13 +759,13 @@
 
 	*output++ = '\0';
 
-	if (FAIL == zbx_mregexp_sub(value->data.str, pattern, output, &new_value))
+	if (FAIL == zbx_regexp_compile_ext(pattern, &regex, 0, &regex_error))
 	{
-		*errmsg = zbx_dsprintf(*errmsg, "invalid regular expression \"%s\"", pattern);
+		*errmsg = zbx_dsprintf(*errmsg, "invalid regular expression: %s", regex_error);
 		return FAIL;
 	}
 
-	if (NULL == new_value)
+	if (FAIL == zbx_regexp_msub_precompiled(value->data.str, regex, output, &new_value))
 	{
 		*errmsg = zbx_dsprintf(*errmsg, "pattern does not match");
 		return FAIL;
@@ -772,6 +774,8 @@
 	zbx_variant_clear(value);
 	zbx_variant_set_str(value, new_value);
 
+	zbx_regexp_free(regex);
+
 	return SUCCEED;
 }
 
@@ -1352,6 +1356,8 @@
 	zbx_variant_t	value_str;
 	int		ret = SUCCEED;
 	char		pattern[ITEM_PREPROC_PARAMS_LEN * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1], *output;
+	const char	*regex_error;
+	zbx_regexp_t	*regex = NULL;
 
 	zbx_variant_set_variant(&value_str, value);
 
@@ -1372,15 +1378,17 @@
 
 	*output++ = '\0';
 
-	if (FAIL == zbx_mregexp_sub(value_str.data.str, pattern, output, error))
+	if (FAIL == zbx_regexp_compile_ext(pattern, &regex, 0, &regex_error))
 	{
-		*errmsg = zbx_dsprintf(*errmsg, "invalid regular expression \"%s\"", pattern);
+		*errmsg = zbx_dsprintf(*errmsg, "invalid regular expression: %s", regex_error);
 		ret = FAIL;
 		goto out;
 	}
 
-	if (NULL != *error)
+	if (SUCCEED == zbx_regexp_msub_precompiled(value->data.str, regex, output, error))
 		ret = FAIL;
+
+	zbx_regexp_free(regex);
 out:
 	zbx_variant_clear(&value_str);
 
Index: src/libs/zbxregexp/zbxregexp.c
===================================================================
--- src/libs/zbxregexp/zbxregexp.c	(revision 86290)
+++ src/libs/zbxregexp/zbxregexp.c	(revision 86291)
@@ -33,6 +33,8 @@
 }
 zbx_regmatch_t;
 
+#define ZBX_REGEXP_GROUPS_MAX	10
+
 /******************************************************************************
  *                                                                            *
  * Function: regexp_compile                                                   *
@@ -89,6 +91,18 @@
 #endif
 }
 
+/*******************************************************
+ *                                                     *
+ * Function: zbx_regexp_compile_ext                    *
+ *                                                     *
+ * Purpose: public wrapper for regexp_compile          *
+ *                                                     *
+ *******************************************************/
+int	zbx_regexp_compile_ext(const char *pattern, zbx_regexp_t **regexp, int flags, const char **error)
+{
+	return regexp_compile(pattern, flags, regexp, error);
+}
+
 /****************************************************************************************************
  *                                                                                                  *
  * Function: regexp_prepare                                                                         *
@@ -151,8 +165,7 @@
 static int	regexp_exec(const char *string, const zbx_regexp_t *regexp, int flags, size_t count,
 		zbx_regmatch_t *matches)
 {
-#define MAX_REQUESTED_MATCHES	10
-#define MATCHES_BUFF_SIZE	(MAX_REQUESTED_MATCHES * 3)
+#define MATCHES_BUFF_SIZE	(ZBX_REGEXP_GROUPS_MAX * 3)
 
 	int				result = 0, r = 0;
 	ZBX_THREAD_LOCAL static int	matches_buff[MATCHES_BUFF_SIZE];
@@ -162,7 +175,7 @@
 	struct pcre_extra		pextra;
 #endif
 
-	if (MAX_REQUESTED_MATCHES < count)
+	if (ZBX_REGEXP_GROUPS_MAX < count)
 		ovector = (int *)zbx_malloc(NULL, ovecsize * sizeof(int));
 	else
 		ovector = matches_buff;
@@ -189,12 +202,11 @@
 	else
 		result = FAIL;
 
-	if (MAX_REQUESTED_MATCHES < count)
+	if (ZBX_REGEXP_GROUPS_MAX < count)
 		zbx_free(ovector);
 
 	return result;
 #undef MATCHES_BUFF_SIZE
-#undef MAX_REQUESTED_MATCHES
 }
 
 /******************************************************************************
@@ -400,10 +412,9 @@
  *********************************************************************************/
 static int	regexp_sub(const char *string, const char *pattern, const char *output_template, int flags, char **out)
 {
-#define MATCH_SIZE 10
 	const char	*error = NULL;
 	zbx_regexp_t	*regexp = NULL;
-	zbx_regmatch_t	 match[MATCH_SIZE];
+	zbx_regmatch_t	 match[ZBX_REGEXP_GROUPS_MAX];
 
 	if (NULL == string)
 	{
@@ -422,8 +433,8 @@
 
 	zbx_free(*out);
 
-	if(ZBX_REGEXP_MATCH == regexp_exec(string, regexp, 0, MATCH_SIZE, match))
-		*out = regexp_sub_replace(string, output_template, match, MATCH_SIZE);
+	if(ZBX_REGEXP_MATCH == regexp_exec(string, regexp, 0, ZBX_REGEXP_GROUPS_MAX, match))
+		*out = regexp_sub_replace(string, output_template, match, ZBX_REGEXP_GROUPS_MAX);
 
 	return SUCCEED;
 #undef MATCH_SIZE
@@ -431,6 +442,50 @@
 
 /*********************************************************************************
  *                                                                               *
+ * Function: zbx_mregexp_sub_precompiled                                         *
+ *                                                                               *
+ * Purpose: Test if a string matches precompiled regular expression. If yes      *
+ *          then create a return value by substituting '\<n>' sequences in       *
+ *          output template with the captured groups.                            *
+ *                                                                               *
+ * Parameters: string          - [IN] the string to parse                        *
+ *             regexp          - [IN] the precompiled regular expression         *
+ *             output_template - [IN] the output string template. The output     *
+ *                                    string is constructed from template by     *
+ *                                    replacing \<n> sequences with the captured *
+ *                                    regexp group.                              *
+ *                                    If output template is NULL or contains     *
+ *                                    empty string then the whole input string   *
+ *                                    is used as output value.                   *
+ *            out              - [OUT] the output value if the input string      *
+ *                                     matches the specified regular expression  *
+ *                                     or NULL otherwise                         *
+ *                                                                               *
+ * Return value: SUCCEED - the regular expression match was done                 *
+ *               FAIL    - failed to match                                       *
+ *                                                                               *
+ * Comments: Multiline match is performed.                                       *
+ *                                                                               *
+ *********************************************************************************/
+int	zbx_regexp_msub_precompiled(const char *string, const zbx_regexp_t *regexp, const char *output_template,
+		char **out)
+{
+	int		ret = FAIL;
+	zbx_regmatch_t	 match[ZBX_REGEXP_GROUPS_MAX];
+
+	zbx_free(*out);
+
+	if(ZBX_REGEXP_MATCH == regexp_exec(string, regexp, 0, ZBX_REGEXP_GROUPS_MAX, match))
+	{
+		ret = SUCCEED;
+		*out = regexp_sub_replace(string, output_template, match, ZBX_REGEXP_GROUPS_MAX);
+	}
+
+	return ret;
+}
+
+/*********************************************************************************
+ *                                                                               *
  * Function: zbx_regexp_sub                                                      *
  *                                                                               *
  * Purpose: Test if a string matches the specified regular expression. If yes    *
