正则表达式负向前瞻失效求助:如何匹配非本站来源的Apache日志行?
Apache日志非本站引用匹配问题
我正在对原始Apache日志进行访客统计分析,需要匹配所有引用URL非本站(example.com)的日志行。以下是两条日志示例:
1.2.3.4 - - [07/Jun/2023:11:15:08 -0500] "GET / HTTP/1.1" 200 - "https://www.google.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36" 1.2.3.4 - - [07/Jun/2023:11:15:08 -0500] "GET /page.html HTTP/1.1" 200 505921 "https://www.example.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
我希望匹配第一条来自Google的引用日志(或其他非本站URL、空引用),但不匹配第二条本站来源的日志。我尝试了以下正则表达式:
/1.2.3.4(.*)GET (/ HTTP|/(.*)htm)(.*)(200|304)(.*)(?!example)/g
去掉(?!example)部分后能匹配所有页面访问行,但加上后无法正常工作,请问我哪里出错了?
问题出在这两点
- 否定断言位置错误:你把
(?!example)放在正则末尾,它只会检查日志行末尾(UA字段附近)是否没有example,但这部分本来就不含该字符串,断言完全没作用在引用URL的位置上。 - 贪婪匹配吞掉目标内容:多个
(.*)是贪婪匹配,会直接跳过引用URL的部分,导致断言根本没机会接触到要检查的example.com。
两个可行的正则方案
方案1:精准定位引用URL并排除本站
专门针对引用URL位置做检查,同时支持匹配空引用(日志中空引用用-表示):
/1\.2\.3\.4.*?"GET (?:\/|\/.*?htm) HTTP\/1\.1" (?:200|304) .*?"(?!https?:\/\/.*example\.com)(?:.*?|-)"/g
.*?"精准定位到引用URL的起始双引号(?!https?:\/\/.*example\.com)确保后续内容不是本站URL(?:.*?|-)匹配非本站URL或空引用- 转义
.和/避免正则语法冲突
方案2:先匹配目标行,再排除本站引用
逻辑更简洁:先匹配所有符合规则的访问行,再排除包含本站引用的条目:
/1\.2\.3\.4.*?"GET (?:\/|\/.*?htm) HTTP\/1\.1" (?:200|304) .*?(?!"https?:\/\/.*example\.com")/g
关键注意点
- 正则中的
.必须转义为\.,否则会匹配任意字符(除换行),引发错误 - 优先用
.*?非贪婪匹配替代.*,避免跳过目标字段 - 否定断言必须放在要检查的内容之前,才能起到过滤作用
内容的提问来源于stack exchange,提问作者Scott
相关产品推荐
相关产品推荐

