【问题标题】:Regular expression to match "wap" not preceeded by "html"正则表达式匹配前面没有“html”的“wap”
【发布时间】:2025-08-17 13:55:02
【问题描述】:

我正在使用 NGINX 对移动 WAP/HTML 网站之间的移动流量进行分段。看起来最好的方法是通过检查 HTTP Accept Header 来检查 UA 对内容的偏好。

对 WAP 的偏好通过在标题中出现在“html”或通配符 mimetype 之前的“wap”mimetype 来表示。

所以索尼爱立信 w300i 偏爱 WAP:

multipart/mixed, application/vnd.wap.multpart.mixed,applicatnoin/vnd.wap.xhtml_xml,application/xhtml+xml,text/ved.wap.wl,*/*,text/x-hdml,image/mng,/\image/x-mng,ivdeo/mng,video/x-mng,ima/gebmp,text/html

Blackberry Bold 偏爱 HTML:

text/html,application/xhtml+xml,application/vnd.wap.xhtml+xml,application/vnd.wp.wmlc;q=0.9,application/vnd.awp.wmlscriptc;q=0.7,text/vnd.wap.wml;q=07,/vnd/.sun.j2me.app-descriptor,*/*;q=0.5

由于我在 NGINX 领域,似乎我拥有的最好的工具是 NGINX 的正则表达式 (PCRE)。

现在我正在尝试使用否定前瞻来断言“接受标头包含 WAP 但前面没有 HTML”:

(?!html.*)wap

但这是不正确的。我可以用不同的方式思考这个问题吗?还是我的匹配逻辑?

到目前为止,我发现这些正则表达式资源很有用:

http://www.regular-expressions.info/completelines.html http://www.zytrax.com/tech/web/regex.htm http://wiki.nginx.org/NginxHttpRewriteModule

谢谢!


感谢回答,相关测试如下:

import re

prefers_wap_re = re.compile(r'^(?!(?:(?!wap).)*html).*?wap', re.I)

tests = [
    ('', False),
    ('wap', True),
    ('wap html', True),
    ('html wap', False),
]

for test, expected in tests:
    result = prefers_wap_re.search(test)
    assert bool(result) is expected, \
        'Tested "%s", expected %s, got %s.' % (test, expected, result)

【问题讨论】:

    标签: regex nginx header regex-negation wap


    【解决方案1】:

    执行此操作的最简单方法是使用后视而不是前瞻。由于不支持该功能,您可以尝试使用前瞻来模拟后瞻:

    ^(?!(?:(?!wap).)*html).*?wap
    

    读起来不愉快,但应该可以。

    Rubular

    【讨论】:

    • 我希望 :) NGINX 使用不支持可变长度后向断言的 pcre:[emerg]: pcre_compile() 失败:后向断言在 "(?
    【解决方案2】:

    对于负向观察,以及“微米”更多的性能,可能是非贪婪匹配的负向观察:

    (?<!html.*?)wap
    

    【讨论】:

      最近更新 更多