[英]Why is my for loop of body.replaceText function in Google Document Script stopping?
[英]Regex match $ but not \$ or $$ in Google Apps Script's body.replaceText()
在Google Apps腳本的body.replaceText()
,我想匹配
$Not\$yes $not $$
^ ^
我可以不加反斜線匹配美元
[^\\]\$
但我不確定如何在文檔開始之前或之后或開始處處理第二個$。
值得注意的是,在body.replaceText()
,“未完全支持JavaScript正則表達式功能的子集,例如捕獲組和模式修飾符。” 堆棧溢出參考
body.replaceText()
: body.replaceText()
方法不支持JavaScript RegExp的某些部分。 眾所周知,模式修飾符( 標志 )不支持捕獲組。
您想要以三個字符序列替換第二個字符,其中第一個和第三個字符不是單個明確指定的字符。 如果沒有前瞻,后視斷言和/或捕獲組,則使用單個正則表達式實際上是不可能的。 可以匹配兩個字符序列[^\\$]\\$
並使用負數預讀(?!\\$)
。 但是,由於Google Apps腳本不支持捕獲組,因此無法僅替換第二個字符$
。
因此,我們需要使用另一種方法,該方法涉及進行多次替換以使文本成為僅可以匹配所需內容的形式。 我們還必須執行其他替換操作,以將文本恢復為原始形式,僅保留所需的操作。
我們有一個普遍的事情(在這種情況下,單個字符$
),這是我們要匹配,但我們想不匹配都非常相似,它(某些特定情況下\\$
和$$
),這將與任何正則表達式匹配用來匹配所需的字符串。 我們需要做的是將那些更改為不匹配的內容,執行所需的操作,然后將其恢復為原來的狀態。
為此,我們需要執行多個替換操作。 下面的代碼顯示了如何完成此操作。
注1:您尚未明確指定在文本中的任何位置還是僅在文檔的開頭或結尾忽略$$
。 那$$$
呢? 當前,下面的代碼將“忽略”連續包含多個$
所有序列。 如果您對要求的要求更為具體,則可以在此處進行更改,也可以僅在自己的代碼中進行更改。
注意2:對於下面的代碼,我假設您只是想對要匹配的$
字符執行replaceText()
。 您實際上並沒有說明要執行的操作,但是該代碼可用於適應所需的任何操作。
//Fake an Object called 'body' so that we can use it as if it was defined // in Google Apps Script by using the statement: // var body = DocumentApp.getActiveDocument().getBody(); var body = new SomeItem('$Not\\\\$yes $not $$'); //The following lines were tested as-is in Google Apps Script: //Open up character sequences which we can be sure are not used in the text. // These sequences can be temporarily used to represent the strings we do not want // to match. In this case we make sure that no 'Q' exists which is not followed // by a `z`. This lets us use any Q[^z] sequence for anything we desire. body.replaceText('Q','Qz'); //Make sure no 'Q' exists that is not 'Qz' //These look a bit strange because we have to use '\\\\' to get a single '\\' within // a string literal. body.replaceText('\\\\\\\\\\\\$','Qa'); //Use `Qa` to represent `\\$` //Use `QbQb` instead of `Qb` because of an issue with restoring and `$` in replacement // string at the end of the string. Also allows handling an odd number of $ in a row. body.replaceText('\\\\$\\\\$','QbQb'); //Use `QbQb` to represent `$$` body.replaceText('Qb\\\\$','QbQb'); //Handle an odd number of $ in a row. Not specified // in the question, but probably desired. //Here we perform whatever operation was desired on all remaining `$`. // In this example we will replace them with '_MATCH_'. // However, for the generalized case, we first we have to perform the // same preliminary substitution which we did to open up character sequences. var newText = '_MATCH_'; body.replaceText('\\\\$',newText.replace(/Q/mg,'Qz')); // Change remaining '$'. //If the replace() is not performed in the above line then any `Qa`, `Qb`, or `Qz` // in the new text will end up being replaced with '\\$', '$' and 'Q' respectively. //Restore the temporary changes body.replaceText('Qa','\\\\$'); //Restore `Qa` to `\\$` body.replaceText('Qb','$'); //Restore `Qb` to `$` body.replaceText('Qz','Q'); //Restore all `Qz` to `Q` //End of lines to be used in Google Apps Script console.log(body.text);
<head> <script> //A function which will perform similar to Google Apps Script so that the // code is closer to what is available there. No provision is made to eliminate // the capture group feature of RegExp. function SomeItem(_text){ this.text = _text; } SomeItem.prototype.replaceText=function (regExString,replaceText){ var theRegExp = new RegExp(regExString,"gm"); this.text = this.text.replace(theRegExp,replaceText); //console.log(regExString,replaceText,this.text); } </script> </head> <body/>
[答案的這一部分是在問題更改為想要與不支持JavaScript RegExp的全部功能的body.replaceText()
一起使用之前提供的。]
您的RegExp實際上並不僅僅與$
匹配。 $
不在字符串開頭時,它將匹配兩個字符。 JavaScript沒有后向斷言,只是先行 ( (?=y)
要求y
跟隨匹配,而(?!y)
要求y
不能跟隨匹配)。 由於JavaScript沒有后向斷言,因此無法僅匹配兩個字符序列中的第二個字符。 另一方面,通過使用先行斷言,我們可以基於以下字符阻止匹配,而無需實際匹配三個字符序列。
要匹配你想要什么,我們必須排除有兩場比賽$
前面的$
和那些下面的字符是匹配$
。 這可以通過以下方法完成:將$
添加到不匹配的字符集中(除了\\
;將其更改為[^\\\\$]
),然后使用(?!\\$)
添加$
的超前排除。
這導致RegExp為:
/(^|[^\\$])\$(?!\$)/g
請注意,這還將您的非捕獲組更改為捕獲組,以便在replace()
使用RegExp時,它可用於恢復$
之前的多余字符。
這是一個使用上述RegExp來匹配您提供的測試字符串的函數示例:
var testMatch = '$Not\\\\$yes $not $$' //Need double \\\\ because it is in a string literal. //Note the use of a capture group and $1 in the replace string to retain the character // prior to the matching '$'. result = testMatch.replace(/(^|[^\\\\$])\\$(?!\\$)/g,'$1_MATCH_'); console.log(result);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.