【问题标题】:Regex to match all except data-value attribute from string正则表达式匹配字符串中除数据值属性之外的所有属性
【发布时间】:2021-11-06 03:45:24
【问题描述】:

我正在寻找一个正则表达式来跳过字符串中的data-value="4" 属性,例如我有一个字符串,即

Hello this is string <sfpart contenteditable="false" data-value="4">&rlm;</sfpart> and the 4 number in string

现在在上面的字符串中,我想用&lt;span class="yellow"&gt;4&lt;/span&gt; 替换4,但不是data-value="4" 内的4

我可以通过以下代码获取4 并用&lt;span class="yellow"&gt;4&lt;/span&gt; 替换它

const reg = new RegExp('('4')', 'gi');
const str = str.replaceAll(reg, '<span class="yellow">$1</span>');

但问题在于正则表达式在 data-value 属性中选择 4 并将其替换为 html span 标签,即 data-value="&lt;span class="yellow"&gt;4&lt;/span&gt;" 所以我想跳过这部分。

有什么可以帮忙的吗?

【问题讨论】:

  • 什么是&lt;sfpart&gt;
  • @Andy 这是来自 DB 的 HTML 标记,这些标记的数据属性中的任何内容都需要被跳过,这样它就不会被替换,即 data-value="&lt;span class="yellow"&gt;4&lt;/span&gt;"

标签: javascript html regex


【解决方案1】:

使用assertions。在这种情况下,消极的回顾:

(?<!data-value=")\d+

这将确保您仅匹配不紧跟在 data-value 属性名称之前的字符 4(以及作为属性值前缀的 =")。

在这里试试:https://regex101.com/r/SzPUOx/1

【讨论】:

  • 这已经足够接近了,但现在有一个问题让我们说如果data-value="14" 在这种情况下它将失败我需要跳过data-value="xxx" 中的任何内容
  • 记住4 是动态的,它可以是任何东西,例如4,42454,test 一个打开的文本字段,输入的任何部分都与data-value="xxx" 匹配,它应该跳过它即输入是569data-valu="15695" 它应该跳过任何一个。
  • 只需将 4 替换为您要匹配的内容。除非您给我您希望匹配的确切字符串,否则我无法有意义地修改我的答案。否则,要真正匹配任何内容,只需将 4 替换为 .*,但我怀疑这不是所需的行为。
  • 我正在寻找的是任何包含在 data-value="xx" 属性中的输入数字,它应该跳过整个数据值属性,例如 data-value="12456" 并且输入的输入数字是 4 我们可以看到 @987654339 @ 存在于 data-value="12345" 中,因此它应该跳过数据值。
  • 如果数据值属性从第一个匹配数字开始,则您的正则表达式 ((?&lt;!data-value=")4) 工作正常,例如如果 data-value="4123" 它跳过(注意 4 在开头)但如果 data-value="1234"data-value="142"4在中间或最后)它不会跳过。
【解决方案2】:

您不应该使用正则表达式来匹配 HTML 标记和属性。改为使用 DOMParser 解析您的字符串,然后遍历所有 nodeChildren 并在文本节点中执行替换(这将具有 3nodeType):

const string = 'Hello this is string <sfpart contenteditable="false" data-value="4">&rlm;</sfpart> and the 4 number in string';

const parser = new DOMParser();
const parsedNode = parser.parseFromString(string, "text/html").body;

for (let i = 0; i < parsedNode.childNodes.length; i++) {
  const node = parsedNode.childNodes[i];
  if (node.nodeType === 3) {
    const replacementNode = document.createElement('span');
    replacementNode.innerHTML = node.textContent.replaceAll(/(\d+?)/gi, '<span class="yellow">$1</span>');
    node.parentNode.insertBefore(replacementNode, node);
    node.parentNode.removeChild(node);
  }
}

console.log(`Input:\n${string}`);
console.log(`Output:\n${parsedNode.innerHTML}`);
document.querySelector('#input').innerHTML = string;
document.querySelector('#output').innerHTML = parsedNode.innerHTML;
#input,
#output {
  border: 1px solid #000;
  padding: 8px;
  margin: 8px;
}

span.yellow {
  background-color: yellow;
}
<strong>Input:</strong>
<div id="input"></div>

<strong>Output:</strong>
<div id="output"></div>

【讨论】:

  • 感谢您的回答特里,但是我不想跳过 HTML 标签,我只需要用&lt;span class="yellow"&gt;4&lt;/span&gt; 替换字符串中的数字,所以最终结果将是这样的Hello this is string &lt;sfpart contenteditable="false" data-value="4"&gt;&amp;rlm;&lt;/sfpart&gt; and the &lt;span class="yellow"&gt;4&lt;/span&gt; number in string
  • @MichaelFine 代码“跳过 HTML 标签”怎么样?它会跳过您所说的不想要的标签本身内的解析属性。您想替换代码中的文本节点中的数字。
  • 特里检查上面的 zr0gravity7 答案可以解决问题,但如果值为14 而不是仅4,则需要进行小幅调整查看他的示例演示链接
  • @MichaelFine 是的,但该答案只能处理一个属性。如果您有任意的data- 属性,例如data-foo="4",那么它将再次失败,因为您需要为每个可以想象的数据属性创建一个lookbehind。
  • 属性永远是data-value="xxx"这是肯定的
猜你喜欢
  • 2019-04-06
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
  • 1970-01-01
  • 1970-01-01
  • 2016-01-10
  • 2020-01-15
  • 2023-01-23
相关资源
最近更新 更多