Используя javascript, как я могу перебирать совпадения регулярных выражений и разбивать строку на массив фрагментов, разделенных гиперссылками?

#javascript #arrays #reactjs #regex

#javascript #массивы #reactjs #регулярное выражение

Вопрос:

У меня есть строка, которую я извлек из api, которая выглядит следующим образом:

 "If you <a href='https://example.com'>Click here</a> then <a href='https://example.net'>Click here</a>."
  

Я пытаюсь создать массив, который выглядит следующим образом:

 [
 "If you "
 <a ... </a>
 " then "
 <a ... </a>
 "."
]
  

По сути, я хочу отобразить его так, как это было задумано, без использования опасно установленного подхода innerHTML.
У меня уже есть совпадения регулярных выражений, я просто пытаюсь найти самый умный способ перебрать их и создать это. Я только что набрал это, но, увидев результат, понял, что он явно ошибочен, мне нужно знать, с чего начать мою подстроку на основе последнего совпадения, но, похоже, не могу разобраться, как к этому подойти. Приветствуется любое руководство

   let noticeTextArr: (string | JSX.Element)[] = [];
  if(notice.label !== undefined) {
    const reg = /<a. ?href="(. ?)".*?>(. ?)</a>/g;
    let resu<
    while((result = reg.exec(notice.label)) !== null) {
      if(result.index > 0) {
        noticeTextArr.push(notice.label.substring(0, result.index))
      }
      noticeTextArr.push(<a href={result[1]}>{result[2]}</a>);      
    }
  }
  

Комментарии:

1. вы можете разделить строку с помощью split, а затем выполнить цикл по массиву. если строка равна «<a>», то подождите, пока не получите </a>. вы можете создать переменную res для хранения данных. Как только вы обнаружите <a>, вставьте данные переменной res в массив. запустите цикл while, пока не получите </a>. Добавьте данные в массив.

2. Я не могу просто разделить строку, потому что я не могу доверять тому, что содержится в строке, поэтому я использую регулярное выражение для поиска совпадений и вручную создаю теги привязки.

3. если вы не доверяете источнику содержимого, то простое извлечение ссылки и их повторное создание не сделает ее более безопасной, если вы каким-то образом не подтвердите фактическое href содержимое.

Ответ №1:

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

 function convertToJSX(text: string) {
  const regex = /<s*a[^>]*href=["']([^>]*)["'][^>]*>(.*?)<s*/s*a>/g;

  const matches = text.matchAll(regex);

  const noticeTextArr: (string | JSX.Element)[] = [];

  let lastIndex = 0;

  for (const match of matches) {
    const [fullMatch, href, content] = match;

    noticeTextArr.push(text.substring(lastIndex, match.index));
    noticeTextArr.push(<a href={href}>{content}</a>);

    lastIndex = match.index   fullMatch.length;
  }

  if (lastIndex < text.length) {
    noticeTextArr.push(text.substring(lastIndex));
  }

  return noticeTextArr;
}

  

Ответ №2:

Вы можете попробовать это:

 const text = "If you <a href='https://example.com'>Click here</a> then <a href='https://example.net'>Click here</a>.";

const array = text.split(/(<a. ?href=["']. ?["'].*?>. ?</a>)/g);
  

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

Ответ №3:

 const data = "If you <a href='https://example.com'>Click here</a> then <a href='https://example.net'>Click here</a>."


const c = data.split(' ')
let i = 0
let res = ''
let arr = []
while(i< c.length){
    if(c[i] === '<a') {
        arr.push(res)
        res = c[i]
        i  ;
        while(!c[i].includes('</a>')) {
          res  = " " c[i]
          i  
        } 
        res  = " " c[i  ]
        arr.push(res)
        res ='';
     } else {
         res  =" "  c[i  ]
     }
  }  
  console.log(arr)  

Ответ №4:

Используйте split с регулярным выражением, имеющим группу захвата:

 const text = "If you <a href='https://example.com'>Click here</a> then <a href='https://example.net'>Click here</a>.";
console.log(text.split(/(<as[^>]*>[^<]*</a>)/));  

Посмотрите, как работает регулярное выражение

Объяснение

                          EXPLANATION
--------------------------------------------------------------------------------
  (                        group and capture to 1:
--------------------------------------------------------------------------------
    <a                       '<a'
--------------------------------------------------------------------------------
    s                       whitespace (n, r, t, f, and " ")
--------------------------------------------------------------------------------
    [^>]*                    any character except: '>' (0 or more
                             times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    >                        '>'
--------------------------------------------------------------------------------
    [^<]*                    any character except: '<' (0 or more
                             times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    <                        '<'
--------------------------------------------------------------------------------
    /                       '/'
--------------------------------------------------------------------------------
    a>                       'a>'
--------------------------------------------------------------------------------
  )                        end of 1
  

Ответ №5:

Поскольку html-элемент сложно разобрать, я бы предложил использовать Document.createElement(), чтобы браузер мог проанализировать и разделить ваш текст:

 var txt = "If you <a href='https://example.com'>Click here</a> then <a href='https://example.net'>Click here</a>.";
var el = document.createElement( 'html' );
el.innerHTML = txt;
var result = Array.from(el.querySelector('body').childNodes).map(function(ele) {
    return ele.nodeType == Node.TEXT_NODE ? ele.textContent : ele.outerHTML;
});

console.log(result);