使用特定元素

时间:2017-01-10 20:20:30

标签: javascript regex algorithm

我有一个字符串“hello @steph你要求的电子邮件是test@test.com用户@test”

我想把它变成:

['hello ', <a href="">@steph</a>, 'the email you requested is test@test.com for user ', <a href="">@test</a>];

这就是我所拥有的:

function matchUserMention(text) {
    var pattern = /\B@[a-z0-9_-]+/gi;
    return text.match(pattern); // [@steph, @test]
}

function applyUser(string) {
    let text = string;
    if (typeof text != 'string') return text;
    var arr = [];

    function replaceAll(str, find, replace) {
        return text.replace(new RegExp(find, 'g'), replace);
    }
    const matches = matchUserMention(text);
    _.each(matches, (match) => {
        text = replaceAll(text, match, <a href={'https://test.co'}>${match}</a>);
    });
    return text; 
}

文本现在返回:

'hello <a href="">@steph</a>, the email you requested is test@test.com for user <a href="">@test</a>

有谁知道从这里创建阵列的最佳方法?因为我需要一直调用它,所以不能重要

4 个答案:

答案 0 :(得分:1)

您可以将split与包含捕获组的正则表达式一起使用。这将导致数组在奇数索引处具有匹配元素。然后,您可以通过<a>.map()换行应用于那些换行符。最后,您可以使用.filter()删除空字符串(例如,在数组的开头或结尾):

&#13;
&#13;
// Sample data
var url = 'https://elk.co';
var string = "hello @steph the email you requested is test@test.com for user @test";

// The transformation
var parts = string.split(/(\B@[\w-]+)/g)
                  .map( (w,i) => i%2 ? `<a href='${url}'>${w}</a>` : w )
                  .filter(Boolean);

// Output the result
console.log(parts);
&#13;
&#13;
&#13;

答案 1 :(得分:1)

function applyUser(string) {
  const reg = /\B@[a-z0-9_-]+/ig;
  const res = [];
  let match;

  // loop while we can match something
  while((match = reg.exec(string)) !== null) {
    // push to result array portion of string before user match, if any
    if (match.index > 0) {
      res.push(string.substring(0, match.index));
    }

    // push updated user name to result array
    res.push('<a href="">' + match[0] + '</a>');

    // remove processed part from a string
    string = string.substr(match.index + match[0].length);
  }

  // push any reminder to the result array
  if (string) {
    res.push(string);
  }
  return res;
}

答案 2 :(得分:0)

此方法与用户名匹配并使用RegExp capability of remembering the last match postion。因此,后续exec()调用将匹配后续用户名。 exec()返回的匹配对象是一个包含匹配文本和指向匹配位置的index属性的数组。

代码将文本从最后一个位置(最初位置0)复制到匹配的用户名,然后附加“包装”用户名并重新开始,直到没有更多的用户名匹配。

代码逐行注释,描述其功能:

function wrapUsernames(str) {
        // match "usernames" ("at" followed by text, preceeded by non-word character or line-start), 
        // the RegExp keeps its state
    var re = /(?:([^\w]|^)(@[a-z]+))/g,
        // store a RegExp match object
        match,
        // store the text fragments
        results = [],
        // remember last index for substring copy
        lastIndex = 0;

    // match and store result, returns null if it does no longer match
    while (match = re.exec(str)) {
        // copy text from last match / start to username 
        // (only if not matched at index 0 to prevent empty string)
        if (match.index != 0) {
            results.push( str.substring(lastIndex, match.index) );
        }
        if (match[1].length >= 1) {
            // it also matched the char before the username, append it
            results.push(match[1]);
        }
        // copy matched username and wrap in a tag
        results.push('<a href="...">' + match[2] + '</a>');
        // update the index to start copy at the next position
        lastIndex = match.index + match[0].length;
    }

    // append the remaining string (only if it wouldn't be an empty string)
    if (lastIndex < str.length) {
        results.push(str.substring(lastIndex));
    }

    return results;
}

这也应匹配前缀为空格以外的其他字符的用户名:

> wrapUsernames("(@steph) the email you requested is test@test.com for user (@test)")
< Array [ "(", "<a href="...">@steph</a>", ") the email you requested is test@test.com for user ", "(", "<a href="...">@test</a>", ")" ]
> wrapUsernames("@steph the email you requested is test@test.com for user (@test)")
< Array [ "<a href="...">@steph</a>", " the email you requested is test@test.com for user ", "(", "<a href="...">@test</a>", ")" ]
> wrapUsernames("hi, @steph the email you requested is test@test.com for user @test")
< Array [ "hi,", " ", "<a href="...">@steph</a>", " the email you requested is test@test.com for user ", " ", "<a href="...">@test</a>" ]

答案 3 :(得分:0)

谢谢大家,这最终成了我用过的,以防万一。这是其他回复的混合。

 function applyUser(str) {
        var arr = [],
            userRegEx = /\B@[a-z0-9_-]+/gi,
            execResult,
            lastFoundLen = 0,
            found,
            strLen = str.length,
            index = 0;
        while ((execResult = userRegEx.exec(str)) !== null) {
            const newIndex = execResult.index;
            if (newIndex > index + lastFoundLen) arr.push(str.substring(index + lastFoundLen, newIndex));
            found = execResult[0];
            if (!found) break;
            const foundLen = found.length;
            const userId = execResult[0].substring(1);
            arr.push(
                <ProfilePersona
                    key={userId}
                    noAvatar
                    view="compact"
                    userId={userId}>
                    {userId}
                </ProfilePersona>
            );

            index = newIndex;
            lastFoundLen = foundLen;
        }
        if (index + lastFoundLen < strLen) arr.push(str.substr(index + lastFoundLen));
        if (!arr.length) arr.push(str);
        return arr;
    }