2014-03-04 61 views
1

在GAS中,我可以正確匹配具有邊界字符的正則表達式的重音,例如\bà\ b。字符à僅在它是單獨的單詞時才匹配。這適用於GAS:BigQuery REGEXP_MATCH和重音:邊界通配符失敗?

function test_regExp() { 
    var str = "la séance est à Paris"; 
    var RegExp = "\\bà\\b"; 
    var PatReg= new RegExp(RegExp); 
    var found=PatReg.exec(str); 
    if (found) { 
    Logger.log([str.substring(0,found.index),found[0],str.substring(found[0].length+found.index)]); 
    } else Logger.log("oops! Did not match"); 

在BigQuery中,如果邊界字符位於重音旁邊,則模式不匹配。 \bséance\ b會與的séance:

SELECT [row],etext,ftext FROM [hcd.hdctextx] WHERE (REGEXP_MATCH(ftext,"\\bséance\\b")) LIMIT 100; 

\Bà\ B不匹配爲一個字:

SELECT [row],etext,ftext FROM [hcd.hdctextx] WHERE (REGEXP_MATCH(ftext,"\\bà\\b")) LIMIT 100; 

我假設的BigQuery,不像天然氣,是包括在邊界字符口音組。所以\bséance\ b可以工作,因爲在該配置中,é可以正常工作作爲邊界。 \bà\ b或\bétranger\ b或\bmarché\ b不起作用,因爲重音符+ \ b被解釋爲\ b \ b,它絕不會匹配任何東西。 (好吧,我在這裏抓着吸管,因爲我找不到更好的解釋......除了一個bug)

我不認爲這是一個Unicode的問題,因爲它只會在邊界位置。

因此,目前沒有辦法在這些特定的口音配置中使用邊界。

有沒有辦法在BigQuery或其他修復中設置區域設置?

解決方法:替代(?:[^ a-zA-Zéàïëëêê])等等\ b。

謝謝!

+0

另一個發現:模式「(?:\\ PL)à」適用於BQ,但不適用於GAS。兩者都應該使用相同的RE實現。可能是因爲這個問題純粹是一個字符集問題,但它看起來像是一個錯誤的RE實現......在一個或另一個或兩個上。 – wgw

回答

4

BigQuery的行爲是對於RE2 syntax documentation正確。 (這並不奇怪,因爲BigQuery使用RE2來實現正則表達式。)

RE2的字符類有:

\b = at word boundary (\w on one side and \W, \A, or \z on the other) 
\w = word characters (≡ [0-9A-Za-z_]) 
\W = not word characters (≡ [^0-9A-Za-z_]) 
\A = beginning of text 
\z = end of text 

換句話說,你只能用\ b鍵相匹配的非重音字符的邊界。不過,RE2有很多對Unicode字符的支持,所以你很可能使用\ pL之類的東西來製作替代的正則表達式。

我不確定爲什麼Google Apps腳本不遵循此處的RE2規範,但我會跟進該團隊以確定發生了什麼。

5

檢查了這一點:

SElect Regexp_extract(StringToParse,r'\b?(à)\b?') as Extract, 
Regexp_match(StringToParse,r'\b?(à)\b?') as match, 
FROM 
(SELECT 'la séance est à Paris' as StringToParse) 

希望這有助於

+1

有趣的想法。到目前爲止,我發現r'\ b?(à)\ b?' BQ是否工作(r'...'語法在GAS中不起作用)。和'\\ b(à)\\ b'(沒有量詞)匹配GAS中的同一事物(GAS不接受\ b上的量詞)。我的應用程序在GAS和BQ中都進行了相同的搜索,但我無法在兩者中使用相同的RE表達式 - 即使文檔說他們使用相同的實現,RE也不會以相同的方式工作!謝謝你的幫助! (我仍在制定一個系統的解決方法。)PS:這種差異似乎影響其他字符類,例如\ PL或\ W。 – wgw

+2

讓我退一步:** r'\ b?(à)\ b?'因爲\ b,它不會在BQ **中工作,因爲它也會檢索Voilà。可以忽略。所以它會找到所有的à,而不是一個單詞,這是\ b ... \ b表達式可以做到的。 (你的建議仍然有幫助,因爲它鼓勵我探索其他同義詞。謝謝!) – wgw

2

答案是:在BQ不使用\ b有口音;重寫規則expresssion:

frenRegExp = frenRegExp.replace(/\\b/g, "(?:[- .,;!?()]|$|^)");  
frenRegExp = frenRegExp.replace(/\\w/g, "(?:[A-Za-zÀàÂâÄäÆæÇçÈèÉéÊêËëÎîÏïÔôÙùÛûÜüñ])"); 
frenRegExp = frenRegExp.replace(/\\W/g, "(?:[^A-Za-zÀàÂâÄäÆæÇçÈèÉéÊêËëÎîÏïÔôÙùÛûÜüñ])"); 

而且,雖然GAS規範有RE2作爲其重新引擎(哎呀我真的不知道是什麼用途,因爲它不從\排除重音符號W¯¯像BQ!) ,它只是部分實施。例如\ pL與字母不匹配。

這是一些測試代碼,適用於應用程序腳本,但不適用於沒有替換的BQ。

////////////////////// TEST /////////////////// 

function test_regExp() { 
    var str = " Voilà la séance générale qui est à Paris"; 
    var RegExpString ="\\bs\\w+an\\w*" 
    Logger.log(RegExpString); 
    var RegExpCompiled= new RegExp(RegExpString,"i"); 
    Logger.log(RegExpCompiled.source); 
    var found=RegExpCompiled.exec(str); 
    if (found) { 
    Logger.log("|"+found[0]+"|") 
    Logger.log([str.substring(0,found.index),found[0],str.substring(found[0].length+found.index)]); 
    } else Logger.log("Oops: not found"); 

} 

輸出:

[16-02-09 22:15:59:659 PST] \bs\w+anc\w* 
[16-02-09 22:15:59:660 PST] \bs\w+an\w* 
[16-02-09 22:15:59:660 PST] |séance| 
[16-02-09 22:15:59:661 PST] [ Voilà la , séance, générale qui est à Paris] 
+0

很好的解釋,謝謝!你如何將特徵請求短語轉發給團隊? –

+0

我認爲這是一個錯誤,實際上,在\ b的情況下。對於GAS來說,這是一個不完整的實施。我會嘗試將它記錄爲一個錯誤(對我來說是第一個錯誤):\ b +重音字符與BQ中的錯誤位置不匹配。就是這樣。 – wgw