Javascript теги регулярного выражения игнорировать - PullRequest
0 голосов
/ 30 марта 2020

У меня есть текст ниже

<span> is an </span>

И я хотел изменить на a , и я использую приведенное ниже регулярное выражение шаблон для этого.

const regExFinder = new RegExp("an", 'gi');
const sourceHTML = "<span> is an </span>";
sourceHTML.replace(regExFinder, `$&`);

Но на выходе получается что-то вроде этого. Кто-нибудь может дать мне представление о том, как пренебрегать любым тегом и изменять только текст внутри тега.

<spa> is a </spa>

А что, если мой источник HTML выглядит так:

<div> an <span> is an </span></div>

Ответы [ 3 ]

1 голос
/ 30 марта 2020

У вас есть несколько вариантов.

const str = "<div> an <span> is an </span></div>";
// method 1: negative lookaheads (probably the best for regex)
str.replace(/an(?![^<>]*>)/gi, "a");
// method 2: rely on having a space after the "an" (not reliable)
str.replace(/an /gi, "a ")
// method 3: rely on "an" being its own word (depends on the situation)
str.replace(/\ban/gi, "a")
1 голос
/ 30 марта 2020

Я анализирую всю строку в элемент DOM, а затем go через все элементы span, чтобы изменить их содержимое с «an» на «a». Метасимвол \b в регулярном выражении обозначает границу слова.

Редактировать:

После более глубокого копания я могу теперь работать со всеми текстовыми узлами и изменять соответствующие строки:

var html='<div> an <span> is an </span>apple and this <span> is a </span> banana.</div>';

var b=document.createElement('body');
b.innerHTML=html;
//               use the "optional filter function" to do the changes:
getTextNodesIn(b,n=>n.textContent=n.textContent.replace(/\ban\b/g,'a'));

// output:
console.log(b.innerHTML);

// I just realised that I can also use Chris West's original function:
// https://cwestblog.com/2014/03/14/javascript-getting-all-text-nodes/
function getTextNodesIn(elem, opt_fnFilter) {
  var textNodes = [];
  if (elem) {
    for (var nodes = elem.childNodes, i = nodes.length; i--;) {
      var node = nodes[i], nodeType = node.nodeType;
      if (nodeType == 3) {
        if (!opt_fnFilter || opt_fnFilter(node, elem)) {
          textNodes.push(node);
        }
      }
      else if (nodeType == 1 || nodeType == 9 || nodeType == 11) {
        textNodes = textNodes.concat(getTextNodesIn(node, opt_fnFilter));
      }
    }
  }
  return textNodes;
}

«Интересный факт»: в нотации ES6 функция может быть переписана еще более коротким способом:

function getTN(elem, opt_flt) {
  if (elem) return [...elem.childNodes].reduce((tn,node)=>{
    var nty = node.nodeType;
    if (nty==3 && (!opt_flt || opt_flt(node, elem))) tn.push(node);
    else if (nty==1 || nty==9 || nty==11)            tn=tn.concat(getTN(node, opt_flt));
    return tn
  }, []);
}
0 голосов
/ 30 марта 2020

Вы можете проверить это решение. Я удалил все теги html из строки, а затем применил операцию замены. Это будет работать для обоих ваших тестовых случаев.

const regExFinder = new RegExp("an", 'gi');
let sourceHTML = "<div> an <span> is an </span></div>";
sourceHTML = sourceHTML.replace(/<[^>]*>?/gm, '').trim();  // removing HTML tags
sourceHTML = sourceHTML.replace(regExFinder, 'a');

console.log(sourceHTML)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...