capability for replacement text in no match regex case added

implemented in property replacer: if a regular expression does not match,
it can now either return "**NO MATCH** (default, as before), a blank
property or the full original property text
This commit is contained in:
Rainer Gerhards 2008-05-30 15:18:03 +02:00
parent 99f18190a1
commit 6a815063f3
5 changed files with 61 additions and 20 deletions

View File

@ -4,6 +4,9 @@ Version 3.19.5 (rgerhards), 2008-05-??
(previously BRE was permitted only)
- provided ability to specify that a regular expression submatch shall
be used inside the property replacer
- implemented in property replacer: if a regular expression does not match,
it can now either return "**NO MATCH** (default, as before), a blank
property or the full original property text
---------------------------------------------------------------------------
Version 3.19.4 (rgerhards), 2008-05-27
- implemented x509/certvalid gtls auth mode

View File

@ -207,16 +207,23 @@ sequence with a regular expression is: "%msg:R:.*Sev:. \(.*\)
\[.*--end%"</p>
<p>It is possible to specify some parametes after the "R". These are
comma-separated. They are:
<p>R,&lt;regexp-type&gt;,&lt;submatch&gt;
<p>R,&lt;regexp-type&gt;,&lt;submatch&gt;,&lt;nomatch&gt;
<p>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.
<p>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.
<p>The following is a sample of an ERE expression that takes the first
submatch from the message string:
<p>%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:
<p>%msg:R,ERE,1,FIELD:for (vlan[0-9]*):--end%
<p><b>Also, extraction can be done based on so-called
"fields"</b>. To do so, place a "F" into FromChar. A field in its
current definition is anything that is delimited by a delimiter

View File

@ -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;
}
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(pTpe->data.field.nomatchAction != TPL_REGEX_NOMATCH_USE_WHOLE_FIELD) {
if (*pbMustBeFreed == 1) {
free(pRes);
*pbMustBeFreed = 0;
}
return "**NO MATCH**";
if(pTpe->data.field.nomatchAction == TPL_REGEX_NOMATCH_USE_DFLTSTR)
return "**NO MATCH**";
else
return "";
}
} else {
/* Match- but did it match the one we wanted? */
/* we got no match! */
if(pmatch[pTpe->data.field.iMatchToUse].rm_so == -1) {
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 "";
}
}
/* OK, we have a usable match - we now need to malloc pB */
int iLenBuf;

View File

@ -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 */

View File

@ -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 */