我偶然发现了这个命名组正则表达式规则,其中作者声称这个正则表达式能够匹配世界上使用最广泛的Web服务器之一的所有可能输出:
(?:(?<network.srcIpv4>(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?<network.srcIpv6>[:\-0-9a-fA-F]+?)|(?<network.srcHost>.+?)) - (?:-|(?<user.username>.+)) \[(?<time>.*)\]\"(?<application.cmd>(?<application.http.method>[A-Z]+)\s(?:(?<application.proto>.*?)://)?(?<network.fqdn>[ˆ/]*?)(?:\:(?<network.dstPort>d+))?(?<file.path>/.*?)?(?:\?(?<application.http.queryString>.*?))?(?: HTTP/(?<application.http.version>[0-9\.]+)?))\" (?<application.http.status>\d+) (?<application.len>\d+)(?:"(?:-|(?<application.http.referrer>.*))")?(?:"(?:-|(?<application.http.userAgent>.*))")?
但是当我尝试它here时,它似乎没有起作用。我知道可以将单个正则表达式写入Apache日志,如下所示:
^(\S+) \S+ \S+ \[([^\]]+)\] "([A-Z]+)[^"]*" \d+ \d+ "[^"]*" "([^"]*)"$
但我更喜欢使用命名的正则表达式,因为它们很容易理解,任何人都可以帮我弄清楚第一个正则表达式有什么问题吗?谢谢。
PS:为了论证,我们假设我的正则表达式是在PHP中。
你可以用
^(?:(?<network_srcIpv4>(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?<network_srcIpv6>[:\-0-9a-fA-F]+?)|(?<network_srcHost>.+?)) - (?:-|(?<user_username>.+)) \[(?<time>.*)\] \"(?<application_cmd>(?<application_http_method>[A-Z]+)\s(?:(?<application_proto>.*?)://)?(?<network_fqdn>[^/]*?)(?:\:(?<network_dstPort>\d+))?(?<file_path>/.*?)?(?:\?(?<application_http_queryString>.*?))?(?: HTTP/(?<application_http_version>[0-9\.]+)?))\" (?<application_http_status>\d+) (?<application_len>\d+) (?:"(?:-|(?<application_http_referrer>.*))")? (?:"(?:-|(?<application_http_userAgent>.*))")$
除了正则表达式中的各种拼写错误(在\
之前缺少\d
以匹配数字,ˆ
而不是^
)和缺少空格,问题是组名称只能以_
或ASCII字母开头,然后最多可以有31个字符。因此,所有.
应该用_
替换或删除。
注意我添加了^
和$
线锚(也请注意启用该行为的m
多线修改器)。如果您不需要整个字符串/行匹配,则可以删除锚点。