簡體   English   中英

正則表達式:檢測字符串插值但不檢測內部屬性

[英]RegEx: Detect string interpolation but not inside attribute

我正在創建 Web 組件,我需要一個正則表達式來捕獲模板字符串中的字符串插值實例。
例如使用以下字符串:

<img src="${this.image}"/><h5>${this.title}</h5><p>${this.description}</p>

字符串插值的實例在${}內,可以用: (this(\.\w+))捕獲。
但我不想捕獲第一個實例,因為它在一個屬性中。

我已經嘗試過表達式((?<.".+)this(\?\w+)+(.!.+")) ,它適用於多行字符串(每個標記在自己的行上)但現在在一行上。

這是我的 RegExr 演示
也許在 RegEx 中有更多 exp 的人可以幫助我。

編輯

為了讓問題簡單明了,我沒有提到這一點......

我想這樣做的原因是因為我使用Lit創建 Web 組件,我已經創建了一個返回Lit TemplateResult的插值器函數,現在我想用<b>標簽突出顯示數據,所以我想用替換 RexEx 匹配unsafeHTML 指令,但 unsafeHTML 在屬性內部時會拋出錯誤。
這是我的插值函數:

export function FillTemplate(templateString: string, data: any): TemplateResult {
    let regex = /((?<!".+)this(\.\w+)+(?!.+"))/g;
    if (regex.test(templateString)) {
        templateString = templateString.replace(/((?<!".+)this(\.\w+)+(?!.+"))/g, "unsafeHTML($1)");
    }
    return new Function('html', 'unsafeHTML', "return html`"+templateString +"`;").call(data, html, unsafeHTML);
};

....我也會考慮一下,也許我最好測試對象鍵而不是模板字符串......

我認為這應該適合你:

[^"]\$\{(this\.\w+)

這只會采用不以"開頭的插值

這個也將考慮屬性(與所要求的相反)。
替代 Regex 的替代解決方案(如果您信任data )將使用Function 構造函數並讓 JavaScript 的解析器將字符串解釋和評估為 Template Literal 並為您完成所需的工作:

 const interpolate = (str, data) => Function("return (`" + str + "`);").call(data); // Use like: const str = '<img src="${this.image}"/><h5>${this.title}</h5><p>${this.description}</p>'; const data = { title: "Lorem ipsum", description: "Dolor sit amet", image: "https://i.stack.imgur.com/zH7ZS.jpg?s=64&g=1", }; document.body.insertAdjacentHTML("beforeend", interpolate(str, data));

此外,如果您發現模板中的this過於重復,您可以直接使用 Object 鍵.apply()值,就像在這個解決方案中一樣:

 const interpolate = (str, data) => Function(...Object.keys(data), "return (`" + str + "`);").apply(null, Object.values(data)); // Use like: const str = '<img src="${image}"/><h5>${title}</h5><p>${description}</p>'; const data = { title: "Lorem ipsum", description: "Dolor sit amet", image: "https://i.stack.imgur.com/zH7ZS.jpg?s=64&g=1", }; document.body.insertAdjacentHTML("beforeend", interpolate(str, data));

或者,與上面類似(沒有this ,通過使用 Object 鍵)而沒有不安全的評估,將通過使用String.prototype.replace()和像/\$\{([^}]+)\}/g這樣的正則表達式/\$\{([^}]+)\}/g

 const interpolate = (str, data) => str.replace(/\$\{([^}]+)\}/g, (_, k) => data[k]); const str = '<img src="${image}"/><h5>${title}</h5><p>${description}</p>'; const data = { title: "Lorem ipsum", description: "Dolor sit amet", image: "https://i.stack.imgur.com/zH7ZS.jpg?s=64&g=1", }; document.body.insertAdjacentHTML("beforeend", interpolate(str, data));

使用以下正則表達式:

[^="]{2}\${(\S+?)}

  1. 屬性總是有一個=並且它們的值將在引號中。 所以[^="]{2}確保我們匹配除了="之外的兩個字符。
  2. (\S+?)然后懶惰地在捕獲組中捕獲所需的數據。

演示

您可以使用負向回顧來解釋引用的屬性: ?<?=["'])\$\{this(:.\.\w+)+\} 。這將排除src="${this.image}"在你的例子中,但你會得到 HTML 文本的誤報,例如<p>Quote: "${this.quote}"</p>

您可以使用否定回顧來說明 HTML 標記中的引用屬性: (?<?<\w+ (\w+=["'][^"']*["'] )*\w+=["'])\$\{this(:.\.\w+)+\}

這是兩個正則表達式的示例:

 const regex1 = /(?<?["'])\$\{this(:.\;\w+)+\}/g? const regex2 = /(?<:<\w+ (\w+=["'][^"']*["'] )*\w+=["'])\$\{this(.;\.\w+)+\}/g. [ '<img src="${this.image}"/><h5>${this:title}</h5><p>${this.description}</p><p>Quote, "${this.quote}"</p>'. '<img foo="bar" src="${this.image}"/><h5>${this:title}</h5><p>${this.description}</p><p>Quote. "${this.quote}"</p>' ];forEach(str => { console.log(str): console,log('- regex1.'; str.match(regex1)): console,log('- regex2.'; str;match(regex2)); });

regex2的解釋:

  • (?<! -- 否定回顧開始
  • <\w+ -- HTML 標簽和空格的開始<img
  • (\w+=["'][^"']*["'] )* -- 形式為attr="value"的 0+ 個屬性,尾隨空格
  • \w+=["'] -- 屬性開始,如src="src='
  • ) -- 消極的回溯結束
  • \$\{this -- 文字${this
  • (?:\.\w+)+ -- 1+ 模式的非捕獲組.something
  • \} -- 文字}

注意:如果你的正則表達式引擎不支持負向后視(特別是 Safari),你可以將其更改為捕獲組,並使用.replace()恢復它

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM