Ruby RegExp中的可选命名组

时间:2018-04-04 07:37:33

标签: ruby regex nginx fluentd

我正在使用插件来解析发送给流利的nginx日志条目,并尝试更改它以便它可选地支持另一个字段。 这是用于解析nginx日志条目config_set_default :expression, %q{/^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/}

的当前REGEXP

我尝试将新字段添加到REGEXP中,如此 - config_set_default :expression, %q{/^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)"(?<http_x_forwarded_for>[^ ]*)?)?$/}

此REGEXP可以解析日志条目是否具有新字段,但仍为新字段创建命名组,这使得现有测试针对插件中断运行。

我想知道是否有某种方法来指示REGEXP它应该添加命名组,如果该组的值存在,并省略该组,否则。

以下是2个日志条目示例,分别包含和不包含新字段 -
127.0.0.1 192.168.0.1 - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777 "-" "Opera/12.0"
127.0.0.1 192.168.0.1 - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777 "-" "Opera/12.0" -

1 个答案:

答案 0 :(得分:1)

您需要在最后一个字段模式后添加(?:\s+(?<http_x_forwarded_for>\S+))?个可选的非捕获组。这意味着命名的捕获组应位于可选的非捕获组内,并且应在其前放置\s+,以便在字段之前考虑任何1个以上的空白字符。

使用

^(?<remote>\S*) (?<host>\S*) (?<user>\S*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^"]*?)(?:\s+\S*)?)?" (?<code>\S*) (?<size>\S*)(?: "(?<referer>[^"]*)" "(?<agent>[^"]*)"(?:\s+(?<http_x_forwarded_for>\S+))?)?$

请参阅regex demo

注意我将[^ ]替换为\S,这更加自然地匹配除空白字符之外的字符和正则表达式。