2015-06-21 61 views
4

任何想法,爲什麼這個簡單的正則表達式似乎沒有在谷歌文檔腳本的支持?replaceText()正則表達式「後面沒有」

foo(?!bar)

我假設Google Apps腳本使用與JavaScript相同的RegEx。這不是嗎?

我使用正則表達式爲這樣:

DocumentApp.getActiveDocument().getBody().replaceText('foo(?!bar)', 'hello'); 

這將生成錯誤:

ScriptError: Invalid regular expression pattern foo(?!bar)

+4

該文檔提到*「JavaScript正則表達式功能的子集不完全支持,例如捕獲組和模式修飾符。」*,似乎此功能確實不受支持.https://developers.google.com/apps-script/reference/document/body#replaceText(String,String) –

+2

值得一提的是,它完全受字符串操作支持......這些限制僅適用於DocumentApp服務。所以應該可以在較低級別上操作文檔(從段落中提取文本等),但它可能會很快變得非常麻煩。直到現在我還沒有找到一個乾淨的解決方案。 –

+0

是的,儘管Google聲稱腳本支持「大部分JavaScript的正則表達式功能」,但它似乎非常有限。 如上所述的消極向前看是非常有用的,很難解決。而且,能夠捕捉文本對於許多查找和替換需求至關重要。 在我的情況下,我能夠通過使用getText(),Javascript的.replace()方法和setText()來解決我的需求。 – Terrence

回答

3

如在關於這個問題的評論所討論的,這是一個記錄限制;該replaceText()方法不支持反向向前看符號或任何其它捕獲基團。

A subset of the JavaScript regular expression features are not fully supported, such as capture groups and mode modifiers.ref

塞爾提出一個變通辦法,「它應該有可能在一個較低的水平,以操縱您的文檔(提取款等文本),但它可能會迅速成爲相當繁瑣。」

這裏有可能是什麼樣子。如果你不介意丟失所有格式,這個例子將適用於捕捉組,正則表達式標誌(i爲不區分大小寫)和反向向前看符號改變:

Little rabbit Foo Foo, running through the foobar.

到:

Little rabbit Fred Fred, running through the foobar.

代碼:

function myFunction() { 
    var body = DocumentApp.getActiveDocument().getBody(); 
    var paragraphs = body.getParagraphs(); 
    for (var i=0; i<paragraphs.length; i++) { 
    var text = paragraphs[i].getText(); 
    paragraphs[i].replaceText(".*", text.replace(/(f)oo(?!bar)/gi, '$1red')); 
    } 
} 
2

你有一個序列,你可以用正則表達式匹配,但正則表達式也將匹配一個或更多的東西,你不希望改變。廣義地解決了這一情況是:

  1. 更改文本,你知道這是絕對不能使用的字符序列。實際上,這會爲您提供一系列字符,您可以將它們用作變量來保存您不想更改的值。就個人而言,我會用:
    body.replaceText('Q','Qz');
    這將使它使得存在你的文件相匹配/Q[^z]/中沒有序列。這使得你能夠使用像序列Qa來表示你不想改變一些文字。我使用Q,因爲它的英文使用頻率很低。你可以使用任何角色。爲了提高效率,請選擇一個字符,這會導致您正在影響的文本內出現少量更改。
  2. 更改你不想落得改變你現在知道的字符序列中的一個事情是不用的。例如:
    body.replaceText('foobar','Qa');
    對於任何您不希望最終更改的項目重複此操作。
  3. 更改你真的想改變的文本。在此示例中: body.replaceText('foo','hello'.replace(/Q/g,'Qz'));
    請注意,您需要將新替換文本應用於用於打開已知未使用序列的第一個替換。
  4. 恢復所有的東西,你不想改變原來的狀態:
    body.replaceText('Qa','foobar');
  5. 恢復您使用未使用的字符序列打通文本:
    body.replaceText('Qz','Q');

總之那會是:

var body = DocumentApp.getActiveDocument().getBody(); 
body.replaceText('Q','Qz');  //Open up unused character sequences 
body.replaceText('foobar','Qa'); //Save the things you don't want to change. 

//In the general case, you need to apply to the new text the same substitution 
// which you used to open up unused character sequences. If you don't you 
// may end up with those sequences being changed in the new text. 
body.replaceText('foo','hello'.replace(/Q/g,'Qz')); //Make the change you desire. 

body.replaceText('Qa','foobar'); //Restore the things you saved. 
body.replaceText('Qz','Q');  //Restore the original sequence. 

在解決問題時,這種方式不允許您使用JavaScript的所有功能RegExp(例如捕獲組,預見斷言和標誌),它應該保留文檔中的格式。

您可以選擇不執行上述步驟1和5,方法是選取一個較長的字符序列來表示您不想匹配的文本(例如kNoWn1UnUsEd)。然而,這樣一個更長的序列是必須根據你對文檔中已經存在的知識的選擇來選擇的。這樣做可以節省幾個步驟,但是您必須搜索未使用的字符串,或者接受使用的字符串已經存在於文檔中的可能性,否則會導致不必要的替換。