我不确定这是可能的,但我一直在尝试从非标准日志格式中提取一条信息。日志可能如下所示
/[^:]*:?([a-zA-Z0-9\-]*[^:]):?/mg
所以我所说的是val将永远存在但是field和extra不会。我正在尝试提出一个正则表达式,无论是否存在字段和额外值,它都将始终提取val。
我最接近的是;
{{1}}
但它仍然不太对劲。只是要注意val不是固定长度。无论是现场也不是额外的。
答案 0 :(得分:4)
(?:([^:\r\n]+):(?=.*:))?([^:\r\n]+)(?::(.+))?
始终将field
与第1组匹配,val
始终与第2组匹配,extra
始终与第3组匹配。如果field
或extra
执行不存在,他们的团体将是空的。
故障:
(?: # begin non-capturing group
([^:\r\n]+) # group 1: any character except ":" or line-break, repeat
: # a ":"
(?=.*:) # must be followed by another ":" somewhere in the remaining string
)? # end group, make optional
( # group 2
[^:\r\n]+ # any character except ":" or line-break, repeat
) # end group 2
(?: # begin non-capturing group
: # a ":"
(.+) # group 3: rest of the line
)? # end group, make optional
前瞻(?=.*:)
是关键部分。它会阻止引擎在val
案例中将"val:extra"
与第1组匹配。
请注意,如果组值可以为空,请执行以下操作:
field1:val1:extra1
:val2:extra1
:val3:
然后只需将捕获组中的+
更改为*
。
答案 1 :(得分:1)
我建议您只使用一个分支重置组,其中包含所有三种可能的备选方案,只需捕获第1组中需要的部分:
^(?|[^:]+:([^:]+):[^:]+|([^:]+):[^:]+|([^:]+))$
请参阅regex demo
<强>详情:
^
- 字符串开头(?|
- 分支重置组启动(内部捕获组ID将从相同的数字开始)
[^:]+:([^:]+):[^:]+
- 3个冒号分开的部分,中间部分被捕获到第1组|
- 或([^:]+):[^:]+
- 2个冒号分隔的部分,第一个被捕获到第1组|
- 或([^:]+) - Group 1 containing just 1 chunk of 1 or more chars other than
:`)
- 分支重置结束$
- 字符串结束。此外,如果您需要将所有部分放入同一个捕获组,我可以建议添加(?J)
PCRE_INFO_JCHANGED 标记并使用命名捕获组:
(?J)^(?:(?<Field>[^:]+):(?<Val>[^:]+):(?<Extra>[^:]+)|(?<Val>[^:]+):(?<Extra>[^:]+)|(?<Val>[^:]+))$