怎么做这个condintional提到RegEx正确吗?

时间:2016-07-12 08:56:34

标签: javascript regex

我使用此标记将提及插入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>

我该如何正确地做到这一点?

2 个答案:

答案 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
})