【问题标题】:Google Analytics Regex - Alternative to no negative lookahead谷歌分析正则表达式 - 替代无负前瞻
【发布时间】:2012-11-13 13:36:39
【问题描述】:

Google Analytics(分析)不再允许在其过滤器中使用负前瞻。事实证明,要创建仅包含我希望包含的链接的自定义报告非常困难。

如果启用它,则包含负前瞻的正则表达式是:

test.com(\/\??index\_(.*)\.php\??(.*)|\/\?(.*)|\/|)+(\s)*(?!.)

这匹配:

test.com
test.com/
test.com/index_fb2.php
test.com/index_fb2.php?ref=23
test.com/index_fb2.php?ref=23&e=35
test.com/?ref=23 
test.com/?ref=23&e=35

并且不匹配(应该如此):

test.com/ambassadors
test.com/admin/?signup=true 
test.com/randomtext/

我正在寻找如何调整我的正则表达式以保持相同的匹配,但不使用负前瞻。

谢谢!

【问题讨论】:

    标签: regex google-analytics


    【解决方案1】:

    Google Analytics 似乎不支持单行和多行模式,这对我来说很有意义。 URL 不能包含换行符,因此点与它们不匹配无关紧要,并且 ^$ 不需要匹配整个字符串的开头和结尾之外的任何位置。

    这意味着你的正则表达式中的(?!.) 完全等同于$,它只匹配字符串的末尾(如\z,在支持它的风格中)。由于这是您的正则表达式中唯一的前瞻,您不应该遇到这个问题;你应该一直在使用$

    但是,您的正则表达式还有其他问题,主要是由于过度依赖(.*)。例如,它匹配这些字符串:

    test.com/?^#(%)!*%supercalifragilisticexpialidocious
    test.com/index_ecky-ecky-ecky-ecky-PTANG!-vroop-boing_rowr.php (ni! shh!)
    

    ...我很确定你不想要。 :P

    试试这个正则表达式:

    test\.com(?:/(?:index_\w+\.php)?(?:\?ref=\d+(?:&e=\d+)?)?)?\s*$
    

    或更易读:

    test\.com
    (?:
      /
      (?:index_\w+\.php)?
      (?:
        \?ref=\d+
        (?:
          &e=\d+
        )?
      )?
    )?
    \s*$
    

    出于说明目的,我对(例如)可以存在哪些参数、它们将出现的顺序以及它们的值可以是什么进行了很多简化假设。我也想知道是否真的有必要匹配域(test.com)。我没有使用 Google Analytics 的经验,但匹配是否应该在 域之后开始(并锚定)?你真的必须在最后允许空格吗?在我看来,正则表达式应该更像这样:

    ^/(?:index_\w+\.php)?(?:\?ref=\d+(?:&e=\d+)?)?$
    

    【讨论】:

    • 非常感谢您的详细回答,但 Google Analytics 显示的匹配项为零。我似乎也无法在在线正则表达式检查器上运行它:regexr.com?32pr7
    • 在测试器中,您应该使用我的第一个正则表达式或从每个 URL 中删除 test\.com。您还需要打开多行模式并删除添加到正则表达式末尾的空间。它仍然不会匹配test.com/?ref=23 行,因为它的末尾也有一个空格。 (这在 GA 中有效吗?我怀疑不是。)
    • 我成功了!我猜最后的空间是问题所在。非常感谢你!您每周在 GA 中使用此自定义报告为我节省了大量时间,并且我学到了很多关于正则表达式的知识。
    • 鉴于它很相似,而且可能是我在正则表达式中遗漏的一些简单的东西,我想知道您是否知道如何解决这个问题? stackoverflow.com/q/58259878/470749 谢谢。
    【解决方案2】:

    首先,我认为您的正则表达式需要一些修复。让我们看看你有什么:

    test.com(\/\??index_.*.php\??(.*)|\/\?(.*)|\/|)+(\s)*(?!.)
    

    index... 的开头使用可选的? 的情况已经被第二种替代方案处理了:

    test.com(\/index_.*.php\??(.*)|\/\?(.*)|\/|)+(\s)*(?!.)
    

    现在您可能只希望允许第一个(.*),如果之前确实有一个文字?。否则你将匹配test.com/index_fb2.phpanystringhereandyouprobablydon'twantthat。所以移动相应的可选标记:

    test.com(\/index_.*.php(\?(.*))?|\/\?(.*)|\/|)+(\s)*(?!.)
    

    现在.* 尽可能多地使用任何字符。此外,php 前面的 . 可以使用任何字符。这意味着您将允许test.com/index_fb2phptest.com/index_fb2.html?someparam=php。让我们将其设为文字 . 并且只允许非问号字符:

    test.com(\/index_[^?]*\.php(\?(.*))?|\/\?(.*)|\/|)+(\s)*(?!.)
    

    现在第一个、第二个和第三个选项可以合并为一个,如果我们也将文件名设为可选:

    test.com(\/(index_[^?]*\.php)?(\?(.*))?|)+(\s)*(?!.)
    

    最后,+ 可以被删除,因为里面的(.*) 已经可以处理所有可能的重复。同样(something|)(something)? 相同:

    test.com(\/(index_[^?]*\.php)?(\?(.*))?)?(\s)*(?!.)
    

    看到您的输入示例,这似乎更接近您实际想要匹配的内容。

    然后回答你的问题。 (?!.) 的作用取决于您是否使用singleline 模式。如果你这样做了,它就断言你已经到达了字符串的末尾。在这种情况下,您可以简单地将其替换为\Z,它始终匹配字符串的结尾。如果你不这样做,那么它断言你已经到了一行的末尾。在这种情况下,您可以使用$,但您还需要使用多行模式,以便$ 也匹配行尾。

    所以,如果您使用singleline 模式(这可能意味着每个字符串只有一个 URL),请使用:

    test.com(\/(index_[^?]*\.php)?(\?(.*))?)?(\s)*\Z
    

    如果您不使用singleline 模式(这可能意味着您可以在自己的行中有多个 URL),您还应该使用multiline 模式和这种锚:

    test.com(\/(index_[^?]*\.php)?(\?(.*))?)?(\s)*$
    

    【讨论】:

    • 非常感谢您的回答。我已经相应地调整了正则表达式。是的,它是单行模式。您对如何改变这一点有什么想法,因此它不需要负前瞻?
    • @eiso 我还添加了一些关于我如何获得简化版本的解释(以及我对您所需匹配的假设是什么)
    • 哇!非常感谢你,我之前的回复还没有看到。
    • 使用正则表达式总能学到更多东西。是否有一种方法不使用负前瞻 ((\s)*$) 的最后一部分,因为 Google Analytics 不接受这一点。
    • @eiso $ 不是负前瞻。它只是一个锚,应该没问题。尝试\Z 而不是$。这实际上更好,因为您无需担心多行模式。
    猜你喜欢
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 2011-10-14
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多