From 6a815063f37e7126f63fa00038f2d050574a6d52 Mon Sep 17 00:00:00 2001
From: Rainer Gerhards
It is possible to specify some parametes after the "R". These are comma-separated. They are: -
R,<regexp-type>,<submatch> +
R,<regexp-type>,<submatch>,<nomatch>
regexp-type is either "BRE" for Posix basic regular expressions or "ERE" for extended ones. The string must be given in upper case. The default is "BRE" to be consistent with earlier versions of rsyslog that did not support ERE. The submatch identifies the submatch to be used with the result. A single digit is supported. Match 0 is the full match, while 1 to 9 are the acutal submatches. +
nomatch is either "DFLT", "BLANK" or "FIELD" (all upper case!). It tells +what to use if no match is found. With "DFLT", the strig "**NO MATCH**" is +used. This was the only supported value up to rsyslog 3.19.5. With "BLANK" +a blank text is used (""). Finally, "FIELD" uses the full property text +instead of the expression. Some folks have requested that, so it seems +to be useful.
The following is a sample of an ERE expression that takes the first -submatch from the message string: -
%msg:R,ERE,1:for (vlan[0-9]*):--end% +submatch from the message string and replaces the expression with +the full field if no match is found: +
%msg:R,ERE,1,FIELD:for (vlan[0-9]*):--end%
Also, extraction can be done based on so-called "fields". To do so, place a "F" into FromChar. A field in its current definition is anything that is delimited by a delimiter diff --git a/runtime/msg.c b/runtime/msg.c index 2798b7be..a90416ff 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -1844,25 +1844,30 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, if(objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) { if (0 != regexp.regexec(&pTpe->data.field.re, pRes, nmatch, pmatch, 0)) { /* we got no match! */ - if (*pbMustBeFreed == 1) { - free(pRes); - *pbMustBeFreed = 0; + if(pTpe->data.field.nomatchAction != TPL_REGEX_NOMATCH_USE_WHOLE_FIELD) { + if (*pbMustBeFreed == 1) { + free(pRes); + *pbMustBeFreed = 0; + } + if(pTpe->data.field.nomatchAction == TPL_REGEX_NOMATCH_USE_DFLTSTR) + return "**NO MATCH**"; + else + return ""; } - return "**NO MATCH**"; } else { -{int i; for(i = 0 ; i < 10 ; ++i) { -dbgprintf("rqtd regex match (nmatch %d) # %d, idx %d: so %d, eo %d\n", nmatch, pTpe->data.field.iMatchToUse, i, -pmatch[i].rm_so, -pmatch[i].rm_eo); -}} /* Match- but did it match the one we wanted? */ /* we got no match! */ if(pmatch[pTpe->data.field.iMatchToUse].rm_so == -1) { - if (*pbMustBeFreed == 1) { - free(pRes); - *pbMustBeFreed = 0; + if(pTpe->data.field.nomatchAction != TPL_REGEX_NOMATCH_USE_WHOLE_FIELD) { + if (*pbMustBeFreed == 1) { + free(pRes); + *pbMustBeFreed = 0; + } + if(pTpe->data.field.nomatchAction == TPL_REGEX_NOMATCH_USE_DFLTSTR) + return "**NO MATCH**"; + else + return ""; } - return "**NO MATCH**"; } /* OK, we have a usable match - we now need to malloc pB */ int iLenBuf; diff --git a/template.c b/template.c index bccc6516..2b336ba9 100644 --- a/template.c +++ b/template.c @@ -521,10 +521,10 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl) /* first come the regex type */ if(*p == ',') { ++p; /* eat ',' */ - if(*p == 'B' && *(p+1) == 'R' && *(p+2) == 'E' && *(p+3) == ',') { + if(p[0] == 'B' && p[1] == 'R' && p[2] == 'E' && (p[3] == ',' || p[3] == ':')) { pTpe->data.field.typeRegex = TPL_REGEX_BRE; p += 3; /* eat indicator sequence */ - } else if(*p == 'E' && *(p+1) == 'R' && *(p+2) == 'E' && *(p+3) == ',') { + } else if(p[0] == 'E' && p[1] == 'R' && p[2] == 'E' && (p[3] == ',' || p[3] == ':')) { pTpe->data.field.typeRegex = TPL_REGEX_ERE; p += 3; /* eat indicator sequence */ } else { @@ -546,6 +546,27 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl) } } + /* now pull what to do if we do not find a match */ + if(*p == ',') { + ++p; /* eat ',' */ + if(p[0] == 'D' && p[1] == 'F' && p[2] == 'L' && p[3] == 'T' + && (p[4] == ',' || p[4] == ':')) { + pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_DFLTSTR; + p += 4; /* eat indicator sequence */ + } else if(p[0] == 'B' && p[1] == 'L' && p[2] == 'A' && p[3] == 'N' && p[4] == 'K' + && (p[5] == ',' || p[5] == ':')) { + pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_BLANK; + p += 5; /* eat indicator sequence */ + } else if(p[0] == 'F' && p[1] == 'I' && p[2] == 'E' && p[3] == 'L' && p[4] == 'D' + && (p[5] == ',' || p[5] == ':')) { + pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_WHOLE_FIELD; + p += 5; /* eat indicator sequence */ + } else { + errmsg.LogError(NO_ERRCODE, "error: invalid regular expression type, rest of line %s", + (char*) p); + } + } + if(*p != ':') { /* There is something more than an R , this is invalid ! */ /* Complain on extra characters */ diff --git a/template.h b/template.h index daeeb5fd..dff06583 100644 --- a/template.h +++ b/template.h @@ -73,6 +73,11 @@ struct templateEntry { TPL_REGEX_BRE = 0, /* posix BRE */ TPL_REGEX_ERE = 1 /* posix ERE */ } typeRegex; + enum { + TPL_REGEX_NOMATCH_USE_DFLTSTR = 0, /* use the (old style) default "**NO MATCH**" string */ + TPL_REGEX_NOMATCH_USE_BLANK = 1, /* use a blank string */ + TPL_REGEX_NOMATCH_USE_WHOLE_FIELD = 2 /* use the full field contents that we were searching in*/ + } nomatchAction; /**< what to do if we do not have a match? */ #endif unsigned has_fields; /* support for field-counting: field to extract */ -- cgit v1.2.3