[英]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+?)}
=
並且它們的值將在引號中。 所以[^="]{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.