谷歌分析正则表达 - 替代没有负面前瞻

时间:2012-11-13 13:36:39

标签: regex google-analytics

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/

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

谢谢!

2 个答案:

答案 0 :(得分:4)

Google Analytics似乎不支持单线和多线模式,这对我来说很有意义。网址不能包含换行符,因此如果点与它们不匹配并不重要,除了整个字符串的开头和结尾之外,任何地方都不需要^$匹配

这意味着你的正则表达式中的(?!.)完全等同于$,它只匹配字符串的最末端(如\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+)?)?$

答案 1 :(得分:1)

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

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模式(这可能意味着您可以在自己的行上拥有多个网址),您还应该使用multiline模式和这种锚点:

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