如何从rsyslog配置文件中提取if-then(含可选else)代码块?
你的原正则if([^}]*)|then([^}]*)|else([^}]*)失效的核心原因是:[^}]*会匹配到第一个闭合大括号就停止,无法处理块内嵌套的{}结构。要完整匹配带有嵌套的条件块,需要用递归匹配平衡大括号的正则逻辑,以下是对应两种需求的解决方案:
需求1:提取指定条件对应的then体(忽略嵌套块的层级,取最外层完整内容)
使用支持PCRE递归语法的正则,匹配if(条件) then { ... }结构,完整捕获then块内的所有内容(包括嵌套的{}):
if\s*\((.*?)\)\s*then\s*\{\s*((?:[^{}]|(?R))*)\s*\}
正则说明:
if\s*\((.*?)\):捕获if后的条件表达式,非贪婪匹配避免跨块\s*then\s*\{\s*:匹配then关键字及后续的左大括号,忽略前后空白字符((?:[^{}]|(?R))*):核心匹配逻辑,[^{}]匹配非括号字符,(?R)递归调用整个正则模式,以此处理嵌套的{},确保匹配到对应的闭合大括号\s*\}:匹配then块的右大括号,忽略空白
示例:
针对如下rsyslog配置:
if ($msg contains 'error') then {
action(type="omfile" file="/var/log/errors.log")
if ($msg contains 'critical') then {
action(type="ommail" to="admin@example.com")
}
}
正则会捕获:
- 条件:
$msg contains 'error' - then体:
action(type="omfile" file="/var/log/errors.log")\n if ($msg contains 'critical') then {\n action(type="ommail" to="admin@example.com")\n }
需求2:提取一级的条件、then体、else体
扩展正则以支持带else的完整块,同时捕获一级的条件、then体和else体:
if\s*\((.*?)\)\s*then\s*\{\s*((?:[^{}]|(?R))*)\s*\}\s*else\s*\{\s*((?:[^{}]|(?R))*)\s*\}
正则说明:
- 前半部分与需求1一致,用于捕获条件和then体
\s*\}\s*else\s*\{\s*:匹配then块结束后的else关键字及左大括号,忽略空白((?:[^{}]|(?R))*)\s*\}:捕获else体,同样通过递归匹配处理嵌套的{}
示例:
针对如下rsyslog配置:
if ($msg contains 'warn') then {
action(type="omfile" file="/var/log/warnings.log")
} else {
action(type="omfile" file="/var/log/other.log")
if ($msg contains 'debug') then {
action(type="omfile" file="/var/log/debug.log")
}
}
正则会捕获:
- 条件:
$msg contains 'warn' - then体:
action(type="omfile" file="/var/log/warnings.log") - else体:
action(type="omfile" file="/var/log/other.log")\n if ($msg contains 'debug') then {\n action(type="omfile" file="/var/log/debug.log")\n }
注意事项:
- 上述正则依赖PCRE的递归匹配特性,需确保使用的工具/语言支持PCRE(如
grep -P、Python的re模块、perl等) - 若要精准匹配某一特定条件,可将正则中的
(.*?)替换为具体的条件表达式(如($msg contains 'error')) \s*已处理配置中的换行、空格等空白字符,适配不同格式的rsyslog配置
内容的提问来源于stack exchange,提问作者ibt23sec5

