Hi,
Have added 3 functions to rainerscript:
- replace(operand, substring_to_be_replaced, its_replacement)
- wrap(operand, string_to_wrap_around_it)
- concat(operand_1, operand_2)
Examples:
replace("foo bar baz", "ba", "BA") => "foo BAr BAz"
concat("foo", "bar") => "foobar"
wrap("hello", "__") => "__hello__"
replace("foo bar", concat("b", "ar"), wrap("baz", "*")) => "foo *baz*"
I felt the need for this while working on some unstructured -> structured
transformation of log-messages. Searched the forums a little, for instance:
http://kb.monitorware.com/modify-message-string-strip-addresses-from-logs-t1610.html
and found that nothing equivalent existed, hence the patch.
0001-... has replace and wrap impl
0002-... has concat impl
(the patches go in the same order)
Im currently running an large installation with these patches applied over
8.4.0, they seem to be working fine.
If the patches look good for merging, I'll be happy to update the
documentation(actually don't know how to update doc yet, will have to dig
in to learn more about it).
--
Regards,
Janmejay
http://codehunk.wordpress.com
From 6d63d27ed0aa710957fd7e325eccab0bf8296ad7 Mon Sep 17 00:00:00 2001
From: Janmejay Singh <[email protected]>
Date: Mon, 13 Oct 2014 16:59:02 +0530
Subject: [PATCH 2/2] adds concat(string, string) as a rainerscript function
---
grammar/rainerscript.c | 30 +++++++++++++++++++++++++++++-
grammar/rainerscript.h | 3 ++-
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index 488dd6c..0f90971 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -1541,6 +1541,7 @@ doFuncWrap(struct var *__restrict__ const sourceVal, struct var *__restrict__ co
es_str_t *sourceStr = var2String(sourceVal, &freeSource);
es_str_t *wrapperStr = var2String(wrapperVal, &freeWrapper);
uchar *src = es_getBufAddr(sourceStr);
+
uchar *wrapper = es_getBufAddr(wrapperStr);
uint lWrapper = es_strlen(wrapperStr);
uint lSrc = es_strlen(sourceStr);
@@ -1556,6 +1557,18 @@ doFuncWrap(struct var *__restrict__ const sourceVal, struct var *__restrict__ co
return res;
}
+static inline es_str_t*
+doFuncConcat(struct var *__restrict__ const firstVal, struct var *__restrict__ const secondVal) {
+ int freeFirst, freeSecond;
+ es_str_t *first = var2String(firstVal, &freeFirst);
+ es_str_t *second = var2String(secondVal, &freeSecond);
+ es_str_t *res = es_newStr(es_strlen(first) + es_strlen(second));
+ es_addStr(&res, first);
+ es_addStr(&res, second);
+ if (freeFirst) es_deleteStr(first);
+ if (freeSecond) es_deleteStr(second);
+ return res;
+}
/* Perform a function call. This has been moved out of cnfExprEval in order
* to keep the code small and easier to maintain.
@@ -1612,6 +1625,14 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct var *__restrict__ con
varFreeMembers(&r[0]);
varFreeMembers(&r[1]);
break;
+ case CNFFUNC_CONCAT:
+ cnfexprEval(func->expr[0], &r[0], usrptr);
+ cnfexprEval(func->expr[1], &r[1], usrptr);
+ ret->d.estr = doFuncConcat(&r[0], &r[1]);
+ ret->datatype = 'S';
+ varFreeMembers(&r[0]);
+ varFreeMembers(&r[1]);
+ break;
case CNFFUNC_GETENV:
/* note: the optimizer shall have replaced calls to getenv()
* with a constant argument to a single string (once obtained via
@@ -3657,7 +3678,14 @@ funcName2ID(es_str_t *fname, unsigned short nParams)
return CNFFUNC_INVALID;
}
return CNFFUNC_WRAP;
- } else {
+ } else if(!es_strbufcmp(fname, (unsigned char*)"concat", sizeof("concat") - 1)) {
+ if(nParams != 2) {
+ parser_errmsg("number of parameters for concat() must be two (string_one, string_two) "
+ "but is %d.", nParams);
+ return CNFFUNC_INVALID;
+ }
+ return CNFFUNC_CONCAT;
+ } else {
return CNFFUNC_INVALID;
}
}
diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
index 514e83a..7e874b8 100644
--- a/grammar/rainerscript.h
+++ b/grammar/rainerscript.h
@@ -260,7 +260,8 @@ enum cnffuncid {
CNFFUNC_LOOKUP,
CNFFUNC_EXEC_TEMPLATE,
CNFFUNC_REPLACE,
- CNFFUNC_WRAP
+ CNFFUNC_WRAP,
+ CNFFUNC_CONCAT
};
struct cnffunc {
--
2.0.4
From a4f907664ef2da8c25fff3877c0b880900333a07 Mon Sep 17 00:00:00 2001
From: Janmejay Singh <[email protected]>
Date: Thu, 9 Oct 2014 13:50:04 +0530
Subject: [PATCH 1/2] rainerscript functions 'replace(operand, str_to_replace,
replacement)' and 'wrap(operand, wrapper_string)' to make some simple
variable tranformations possible
---
grammar/rainerscript.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++
grammar/rainerscript.h | 4 +-
2 files changed, 110 insertions(+), 1 deletion(-)
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index ccfa0e2..488dd6c 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -1482,6 +1482,81 @@ doFunc_exec_template(struct cnffunc *__restrict__ const func,
}
+static inline es_str_t*
+doFuncReplace(struct var *__restrict__ const operandVal, struct var *__restrict__ const findVal, struct var *__restrict__ const replaceWithVal) {
+ int freeOperand, freeFind, freeReplacement;
+ es_str_t *str = var2String(operandVal, &freeOperand);
+ es_str_t *findStr = var2String(findVal, &freeFind);
+ es_str_t *replaceWithStr = var2String(replaceWithVal, &freeReplacement);
+ uchar *find = es_getBufAddr(findStr);
+ uchar *replaceWith = es_getBufAddr(replaceWithStr);
+ uint lfind = es_strlen(findStr);
+ uint lReplaceWith = es_strlen(replaceWithStr);
+ uint size = 0;
+ uchar* src = es_getBufAddr(str);
+ uint i, j;
+ for(i = j = 0; i < es_strlen(str); i++, size++) {
+ if (j == lfind) {
+ size = size - lfind + lReplaceWith;
+ j = 0;
+ } else if (src[i] == find[j]) {
+ j++;
+ } else if (j > 0) {
+ j = 0;
+ }
+ }
+ es_str_t *res = es_newStr(size);
+ unsigned char* dest = es_getBufAddr(res);
+ uint k, s;
+ for(i = j = k = s = 0; i < es_strlen(str); i++, s++) {
+ if (j == lfind) {
+ for (k = 0; k < lReplaceWith; k++) {
+ dest[s - j + k] = replaceWith[k];
+ }
+ s = s - j + lReplaceWith;
+ j = 0;
+ dest[s] = src[i];
+ } else {
+ if (src[i] == find[j]) {
+ j++;
+ } else if (j > 0) {
+ j = 0;
+ for (k = 0; k < j; k++) {
+ dest[s - j + k] = find[k];
+ }
+ }
+ dest[s] = src[i];
+ }
+ }
+ res->lenStr = size;
+ if(freeOperand) es_deleteStr(str);
+ if(freeFind) es_deleteStr(findStr);
+ if(freeReplacement) es_deleteStr(replaceWithStr);
+ return res;
+}
+
+static inline es_str_t*
+doFuncWrap(struct var *__restrict__ const sourceVal, struct var *__restrict__ const wrapperVal) {
+ int freeSource, freeWrapper;
+ es_str_t *sourceStr = var2String(sourceVal, &freeSource);
+ es_str_t *wrapperStr = var2String(wrapperVal, &freeWrapper);
+ uchar *src = es_getBufAddr(sourceStr);
+ uchar *wrapper = es_getBufAddr(wrapperStr);
+ uint lWrapper = es_strlen(wrapperStr);
+ uint lSrc = es_strlen(sourceStr);
+ uint totalLen = lSrc + 2 * lWrapper;
+ es_str_t *res = es_newStr(totalLen);
+ uchar* resBuf = es_getBufAddr(res);
+ memcpy(resBuf, wrapper, lWrapper);
+ memcpy(resBuf + lWrapper, src, lSrc);
+ memcpy(resBuf + lSrc + lWrapper, wrapper, lWrapper);
+ res->lenStr = totalLen;
+ if (freeSource) es_deleteStr(sourceStr);
+ if (freeWrapper) es_deleteStr(wrapperStr);
+ return res;
+}
+
+
/* Perform a function call. This has been moved out of cnfExprEval in order
* to keep the code small and easier to maintain.
*/
@@ -1519,6 +1594,24 @@ doFuncCall(struct cnffunc *__restrict__ const func, struct var *__restrict__ con
}
ret->datatype = 'N';
break;
+ case CNFFUNC_REPLACE:
+ cnfexprEval(func->expr[0], &r[0], usrptr);
+ cnfexprEval(func->expr[1], &r[1], usrptr);
+ cnfexprEval(func->expr[2], &r[2], usrptr);
+ ret->d.estr = doFuncReplace(&r[0], &r[1], &r[2]);
+ ret->datatype = 'S';
+ varFreeMembers(&r[0]);
+ varFreeMembers(&r[1]);
+ varFreeMembers(&r[2]);
+ break;
+ case CNFFUNC_WRAP:
+ cnfexprEval(func->expr[0], &r[0], usrptr);
+ cnfexprEval(func->expr[1], &r[1], usrptr);
+ ret->d.estr = doFuncWrap(&r[0], &r[1]);
+ ret->datatype = 'S';
+ varFreeMembers(&r[0]);
+ varFreeMembers(&r[1]);
+ break;
case CNFFUNC_GETENV:
/* note: the optimizer shall have replaced calls to getenv()
* with a constant argument to a single string (once obtained via
@@ -3550,6 +3643,20 @@ funcName2ID(es_str_t *fname, unsigned short nParams)
return CNFFUNC_INVALID;
}
return CNFFUNC_LOOKUP;
+ } else if(!es_strbufcmp(fname, (unsigned char*)"replace", sizeof("replace") - 1)) {
+ if(nParams != 3) {
+ parser_errmsg("number of parameters for wrap() must be three (operand_string, fragment_to_find, fragment_to_replace_in_its_place) "
+ "but is %d.", nParams);
+ return CNFFUNC_INVALID;
+ }
+ return CNFFUNC_REPLACE;
+ } else if(!es_strbufcmp(fname, (unsigned char*)"wrap", sizeof("wrap") - 1)) {
+ if(nParams != 2) {
+ parser_errmsg("number of parameters for wrap() must be two (operand_string, string_to_wrap_it_in) "
+ "but is %d.", nParams);
+ return CNFFUNC_INVALID;
+ }
+ return CNFFUNC_WRAP;
} else {
return CNFFUNC_INVALID;
}
diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
index 8742c75..514e83a 100644
--- a/grammar/rainerscript.h
+++ b/grammar/rainerscript.h
@@ -258,7 +258,9 @@ enum cnffuncid {
CNFFUNC_FIELD,
CNFFUNC_PRIFILT,
CNFFUNC_LOOKUP,
- CNFFUNC_EXEC_TEMPLATE
+ CNFFUNC_EXEC_TEMPLATE,
+ CNFFUNC_REPLACE,
+ CNFFUNC_WRAP
};
struct cnffunc {
--
2.0.4
_______________________________________________
rsyslog mailing list
http://lists.adiscon.net/mailman/listinfo/rsyslog
http://www.rsyslog.com/professional-services/
What's up with rsyslog? Follow https://twitter.com/rgerhards
NOTE WELL: This is a PUBLIC mailing list, posts are ARCHIVED by a myriad of
sites beyond our control. PLEASE UNSUBSCRIBE and DO NOT POST if you DON'T LIKE
THAT.