reactStringReplace:使用捕获组正则表达式

时间:2018-05-25 00:58:00

标签: javascript regex reactjs

来自https://github.com/iansinnott/react-string-replace/issues/33

的共享问题

react-string-replace:https://github.com/iansinnott/react-string-replace

我无法使用reactStringReplace格式化带粗体/斜体标签的文字。我把它设置如下:

var text1 = "[b]Testing bold [i]and italic[/i] tags[/b]"
var text2 = "[b]Testing bold [i]and italic tags[/b][/i]"

let replaced = reactStringReplace(text1, /\[b\]([\s\S]+)\[\/b\]/g, (match, i) => {
   return <b key={i}>{match}</b>
})
replaced = reactStringReplace(replaced, /\[i\]([\s\S]+)\[\/i\]/g, (match, i) => {
   return <i key={i}>{match}</i>
})

// result (html)
<b>Testing [i]bold and italic[/i] tags</b>
<b>Testing [i]bold and italic tags</b>[/i]

我不确定这是reactStringReplace的问题,我正在使用正则表达式,还是其他什么。如果我首先应用斜体替换,我会得到斜体标签,我希望它们是,但[b]标签保持不变。这个用例是否可以使用reactStringReplace,还是需要使用dangerouslySetInnerHtml

Bonus:reactStringReplace是否能够处理不平衡的标签,或text2中不正确格式化的标签,或者我应该进行一些预处理以确保字符串正确平衡和格式化?

1 个答案:

答案 0 :(得分:1)

您的样本有多个问题,

  • 您不使用推荐的JSX密钥格式<i key={match + i}>{match}</i>(见下文)
  • 您的比赛重叠
  • 你贪婪的+量词可能会匹配太多。
  • 缺少;等等。

广告。 1:引用完整的example

  

在许多React示例中,您会看到使用的iindex变量   作为JSX标记的关键(例如本例中的<a>标记),但在这种情况下,我们在三个独立的循环中进行迭代。   这意味着我们不能使用key={i}因为所有三个JSX   标签可以获得相同的密钥。

广告。 2:然而,最重要的部分是你的匹配重叠,这与reactStringReplace不相符。

示范:

const text = 'Hey @ian_sinn#reactconf';
let replacedText;

// Match @-mentions
replacedText = reactStringReplace(text, /@(\w+)/g, (match, i) => (
  <b key={match + i}>@{match}</b>
));

// Match hashtags
replacedText = reactStringReplace(replacedText, /#(\w+)/g, (match, i) => (
  <a key={match + i} href={`https://twitter.com/hashtag/${match}`}>#{match}</a>
));

我们在此示例中有不同的匹配:首先,@ian_sinn匹配并替换,然后#reactconf,因此替换按预期工作;但是,如果您使用\w更改替换.的第一个正则表达式,则会出现重叠匹配:现在,第二个替换将不会应用。

如果您避免重叠匹配,它会起作用:

render() {    
    const text = '[b]Testing bold [i]and italic[/i] tags[/b]';
    let replacedText;

    replacedText = reactStringReplace(text, /\[b\]((?:(?!\[\/b\]|\[i\]|\[\/i\]).)*)/g, (match, i) => (
      <b key={match + i}>{match}</b> 
    ));

    replacedText = reactStringReplace(replacedText, /\[i\]((?:(?!\[\/b\]|\[i\]|\[\/i\]).)*)/g, (match, i) => (
      <b><i key={match + i}>{match}</i></b>
    ));

    replacedText = reactStringReplace(replacedText, /\[\/i\]((?:(?!\[\/b\]|\[i\]|\[\/i\]).)*)/g, (match, i) => (
      <b key={match + i}>{match}</b>
    ));

    replacedText = reactStringReplace(replacedText, /\[\/b\]((?:(?!\[\/b\]|\[i\]|\[\/i\]|$).)*)$/g, (match, i) => (
      <b key={match + i}>{match}</b>
    ));

    return (
      <div>
        {replacedText}
      </div>
    );
  },
});

但是这需要你在这个问题上抛出更复杂的正则表达式,给你丑陋的标记,并且可以说,打败了整个冒险的目的......

广告。 3:使用不匹配的匹配将其与简单的香草正则表达替换进行比较:[\s\S]+?

const str = `[b]Testing bold [i]and italic[/i] tags[/b]`;
const result = str.replace(/\[b\]([\s\S]+?)\[\/b\]/gm, `<b>$1</b>`)
                  .replace(/\[i\]([\s\S]+?)\[\/i\]/gm, `<i>$1</i>`);
console.log('Substitution result: ', result);

判决:伤心,但现在official。截至目前,reactStringReplace不处理嵌套替换:

  

因为替换可以将数据类型更改为其他内容   字符串。如果你看这里你会看到它只运行替换   字符串。一旦你的第一次替换已经运行了元素   结果数组将是一个对象(即<b>...</b>),因此没有替换   将在内部字符串上运行。