如何用正则实现符合WhatsApp规则的文本格式转换?
符合WhatsApp规则的文本格式转换(正则实现方案)
需求说明
需要将采用WhatsApp/StackOverflow风格的文本标记转换为对应HTML标签:
*→<b>(粗体)_→<i>(斜体)~→<s>(删除线)
同时必须满足WhatsApp的两个特殊规则:
- 触发条件限制:仅当标记前是特定字符(
,:;空格_ ~ . \n *)时才转换,例如@*this text is not bold*保持原样; - 连续标记限制:标记连续数量超过2个时不转换,例如
***this text is not bold**保持原样。
正则实现方案
可以通过结合反向预查、正向预查和数量限定实现符合规则的匹配,以下分标记类型给出具体正则及替换逻辑(以JavaScript为例):
1. 粗体标记(*)转换
正则匹配规则:
/(?<=^|[:,; _~.\n*])(\*{1,2})(?!\*)([^*]+?)\1(?=$|[:,; _~.\n*])/g
替换为:<b>$2</b>
2. 斜体标记(_)转换
正则匹配规则:
/(?<=^|[:,; _~.\n*])(_{1,2})(?!_)([^_]+?)\1(?=$|[:,; _~.\n*])/g
替换为:<i>$2</i>
3. 删除线标记(~)转换
正则匹配规则:
/(?<=^|[:,; _~.\n*])(~{1,2})(?!~)([^~]+?)\1(?=$|[:,; _~.\n*])/g
替换为:<s>$2</s>
正则逻辑解释
- 反向预查
(?<=^|[:,; _~.\n*]):确保标记前是允许的特定字符或文本开头,对应规则1; - 数量限定
{1,2}:只匹配1-2个连续标记,超过2个的不触发转换,对应规则2; - 正向预查
(?!\*)(对应*标记):避免误匹配3个及以上的连续标记; - 非贪婪捕获组
([^*]+?):精准匹配标记包裹的内容,支持嵌套标记的逐层转换(如~_*text*_~会依次转换为<s><i><b>text</b></i></s>)。
完整示例代码
function convertWhatsAppMarkup(text) { // 按外层到内层顺序处理嵌套标记 text = text.replace(/(?<=^|[:,; _~.\n*])(~{1,2})(?!~)([^~]+?)\1(?=$|[:,; _~.\n*])/g, '<s>$2</s>'); text = text.replace(/(?<=^|[:,; _~.\n*])(_{1,2})(?!_)([^_]+?)\1(?=$|[:,; _~.\n*])/g, '<i>$2</i>'); text = text.replace(/(?<=^|[:,; _~.\n*])(\*{1,2})(?!\*)([^*]+?)\1(?=$|[:,; _~.\n*])/g, '<b>$2</b>'); return text; } // 测试输入 const input = `*this text is bold*, _this text is italic_, ~this text is strikethrough~. ~_*this text is bold, italic and strike-through*_~ @*this text is not bold* ***this text is not bold**`; // 输出转换结果 console.log(convertWhatsAppMarkup(input));
输出结果:
<b>this text is bold</b>, <i>this text is italic</i>, <s>this text is strikethrough</s>. <s><i><b>this text is bold, italic and strike-through</b></i></s> @*this text is not bold* ***this text is not bold**
内容的提问来源于stack exchange,提问作者Sayad Ahmed Shaurov
相关产品推荐
相关产品推荐

