2012-11-13 47 views
4

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/ 

我正在尋找如何適應我的正則表達式仍然持有相同的比賽,但沒有使用消極的LO okahead。

謝謝!

回答

3

谷歌分析似乎並不支持單和多行模式,這對我來說很有意義。網址不能包含換行符,所以點不匹配它們並沒有關係,並且從不需要^$以匹配整個字符串的開頭和結尾的任何位置。

這意味着您的正則表達式中的(?!.)完全等同於$,它僅在字符串的最後匹配(如\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+)?)?$ 
+0

非常感謝您提供詳細的答案,但Google Analytics(分析)顯示的結果爲零。我似乎也無法讓它在在線正則表達式檢查器上工作:http://regexr.com?32pr7 – eiso

+1

在測試儀中,您應該使用我的第一個正則表達式或從每個URL中刪除'test \ .com' 。您還需要打開多行模式並擺脫添加到正則表達式結尾的空間。它仍然不符合'test.com/?ref = 23'這一行,因爲它最後也有一個空格。 (這在GA中有效嗎?我懷疑不是。) –

+0

我明白了!我想最後的空間是問題所在。非常感謝你!通過GA中的這份定製報告,您每週都爲我節省了大量時間,並且我學到了很多關於正則表達式的知識。 – eiso

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)*$ 
+0

非常感謝你的回答。我相應地調整了正則表達式。是的,它是單線模式。你對如何改變這個問題有任何想法,所以它不需要負向預測? – eiso

+0

@eiso我也在一些解釋中加入了我如何得到簡化版本(以及我對你想要的匹配的假設) –

+0

哇!非常感謝你,我還沒有看到我的回覆。 – eiso