我使用此标记将提及插入textareas:
@User Name Can Have Spaces(userId: number)
例如@Javier Hernadez(5)
我有一个JSON用户列表:
var users = [{name: 'Javier Hernandez',id: 5},{...}];
现在我想将标记转换为纯HTML代码:
var myHtml = "..."; // loaded externally and contains the markup
var matches = myHtml.match(/@([a-z\d_]+)/ig);
但这对于带空格的用户名不起作用,我不会获得用户ID。
我现在迭代匹配,检查标记中的用户是否存在于我的users
数组中并替换模板字符串中的匹配
<a href="path/to/user/{id}>{name}</a>
我该如何正确地做到这一点?
答案 0 :(得分:1)
首先,分析您当前的正则表达式及其不起作用的原因:
@
是文字@
字符,此处无处可见[...]
是一个角色类。它将匹配它包含的任何(一个)字符[a-z\d_]
是一个由每个小写字母,每个数字(由他们自己的字符类\d
表示)和下划线+
是一个量词,表示它修改的令牌必须至少匹配一次,并且可以匹配多次。这里它适用于前一个字符类/pattern/flags
是Javascript的正则表达式语法之一i
是不区分大小写的标志。在这种情况下,它意味着字符类也将匹配大写字母,尽管它只包含小写字母g
是全球旗帜。这意味着正则表达式将尝试匹配多个结果,而不是在第一次遇到时返回。所以你试图匹配@User Name Can Have Spaces(userId: number)
,但你的正则表达式与你提到的空格不匹配,也不是括号。
您可以将这三个字符添加到字符类中,如下所示:
/@([a-z\d_ ()]+)/gi
然而,至少在我看来,对你想要匹配的内容的更好的描述将是:
/@[a-z\d_ ]+\(\d+\)/gi
我们匹配的用户名可以包含字母,数字,下划线和空格,后跟左括号,数字和右括号。必须对括号进行转义,以便将它们理解为文字字符,而不是正则表达式组。
如果您想分别轻松提取用户名和用户ID,您可能需要使用以下内容,它们分别在各自的组中分组:
/@([a-z\d_ ]+)\((\d+)\)/gi
这是一个regex101 link来测试它。
答案 1 :(得分:0)
您可以先将users
转换为哈希值。
var usersCache = users.reduce(function(acc, user) {
acc[user.id] = user.name;
return acc;
}, {})
然后用regexp替换
myHtml = myHtml.replace(/@[^(]+\((\d+)\)/g, function(all, id) {
// if id is unknown leave original string
// else replace with an anchor taking name from users list
return usersCache[id]
? ('<a href="path/to/user/'+ id + '">' + userCache[id] + '</a>')
: all
})