Как добавить настраиваемые теги в текст и вставить другой текст?

#javascript #regex

Вопрос:

Вопрос заголовка может быть непростым для понимания. Надеюсь, вы сможете понять мою подробную информацию ниже.

У меня есть данные предложения ниже, в которых есть некоторые теги, представленные [tn]tag[/tn] :

 const sentence = `[t1]Sometimes[/t1] that's [t2]just the way[/t2] it has to be. Sure, there
 were [t3]probably[/t3] other options, but he didn't let them [t4]enter his mind[/t4]. It 
was done and that was that. It was just the way [t5]it[/t5] had to be.`
 

И у меня есть части предложения.

 const parts = [
    "Sometimes that's just the way",
    "it has to be",
    "Sure,",
    "there were probably other options,",
    "but he didn't let them enter his mind.",
    "It was done and that was that.",
    "It was just the way it had to be."
];
 

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

 const expectedOutput = [
    "[t1]Sometimes[/t1] that's [t2]just the way[/t2]",
    "it has to be",
    "Sure,",
    "there were [t3]probably[/t3] other options,",
    "but he didn't let them [t4]enter his mind[/t4].",
    "It was done and that was that.",
    "It was just the way [t5]it[/t5] had to be."
];
 

До сих пор я пробовал следующее, но, похоже, это не имеет смысла, и в итоге я ничего не добился.

  1. сделайте предложение-клон и удалите все теги. (код ниже)
  2. найдите все части предложения.
  3. [проблема в том, что я не знаю, как снова поставить теги]

Я хочу спросить, есть ли какой-нибудь шанс достичь этого? и как. Спасибо


 export const removeTags = (content) => {
  content = content.replace(/([t]|[/t])/g, '');
  return content.replace(/([td ]|[/td ])/g, '');
};
 

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

1. Вы должны показать, что вы пробовали до сих пор

2. @SubhashisPandey я обновил и добавил некоторый фрагмент кода, который я пробовал. Я не хочу помещать весь код целиком, потому что это удлиняет описание вопроса и в любом случае имеет смысл.

3. возможно ли, что теги распределены между двумя или более частями предложения? Например, t1 начинается с частей[0] и заканчивается частями[2] ?

4. Это не ваша главная проблема, но вам нужно избежать всех «в строках». Например, «Когда-нибудь это будет именно так». В противном случае ваш код не будет работать.

5. @thchp нет, сэр. этого не могло быть. мы фиксируем это перед сохранением в БД.

Ответ №1:

Для ответа на регулярное выражение: /[td ]([^[]*)[/td ]/g сопоставит все слова, включая теги, а затем сгруппирует все слова в этих тегах.

 let regex = /[td ]([^[]*)[/td ]/g;
let matches = [], tags = [];
var match = regex.exec(sentence);
while (match != null) {
    tags.push(match[0]);
    matches.push(match[1]);
    match = regex.exec(sentence);
}
 

теперь нам просто нужно заменить все matches на tags внутри parts

 let lastSeen = 0;
for (let i = 0; i < parts.length; i  ) {
    for (let j = lastSeen; j < matches.length; j  ) {
        if (parts[i].includes(matches[j])) {
            lastSeen  ;
            parts[i] = parts[i].replaceAll(matches[j], tags[j])
        } else if (j > lastSeen) {
            break;
        }
    }
}
 

Вот ссылка для просмотра регулярного выражения: regex101

И вот JSFiddle, чтобы увидеть все это, JSFiddle

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

1. о, подождите, сэр. он не принимает теги из 2 цифр. например [t12]word[/t12] ??

2. просто обновите регулярное выражение /[td ]([^[]*)[/td ]/g

3. Я отредактировал сообщение, чтобы включить поддержку нескольких чисел в теги с регулярным выражением от @thchp

Ответ №2:

Здесь я также сделал альтернативную версию, поэтому просто сброшу ее ниже. Нет вложенности, как в @thchp, но немного легче читать имо.

 const sentence = "[t1]Sometimes[/t1] that's [t2]just the way[/t2] it has to be. Sure, there"  
 "were [t3]probably[/t3] other options, but he didn't let them [t4]enter his mind[/t4]. It "  
 "was done and that was that. It was just the way [t5]it[/t5] had to be.";

const parts = [
    "Sometimes that's just the way",
    "it has to be",
    "Sure,",
    "there were probably other options,",
    "but he didn't let them enter his mind.",
    "It was done and that was that.",
    "It was just the way it had to be."
];

const getTokens = (text) => {
  const tokens = text.match(/[t[0-9] ]/gm);
  const result = [];
  
  tokens.forEach(tokenOpen => {
    const tokenClose = "[/"   tokenOpen.substring(1, tokenOpen.length);
    const tokenStart = text.indexOf(tokenOpen)   tokenOpen.length;
    const tokenEnd = text.indexOf(tokenClose);
    result.push({
        tokenOpen,
      tokenClose,
        value: text.substr(tokenStart, tokenEnd - tokenStart)
    });
  });
  
  return resu<
}

const applyTokens = (parts, tokens) => {
    return parts.map(part => {
        const match = tokens.filter(x => part.includes(x.value));

        if(!match.length)
            return part;
    
        const {value, tokenOpen, tokenClose} = match[0];
        const index = part.indexOf(value);
        const partPre =  part.substr(0, index);
        const partPost = part.substr(index   value.length, part.length);
        return partPre   tokenOpen   part.substr(index, value.length)   tokenClose   partPost;
    });
}

const output = applyTokens(parts, getTokens(sentence));

console.log(output);
 

Он добавляет теги ко всем вхождениям некоторого значения в детали, поэтому первое «оно» во втором элементе массива «детали» также оборачивается. Если вы не хотите этого, удалите один раз использованный токен в «applyTokens».

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

1. спасибо за это, сэр. я попробую это сделать. на мгновение.

2. Кроме того, я только что провел сравнительный анализ обоих решений, и это, вероятно, быстрее. Хотя это удивительно, так как стандартное зацикливание массива должно быть быстрее, чем .map .forEach

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

Ответ №3:

Вот решение, которое предполагает, что вложенных тегов нет, что все теги открываются и закрываются в детали. Кроме того, это предполагает, что все символы из предложения находятся внутри parts . Для этого последнего предположения мне пришлось добавить . «после», которое должно быть во второй ожидаемой части. Мне также пришлось удалить символы новой строки из предложения, но я думаю, что это было из-за копирования/вставки. Это решение будет перебирать все символы и хранить два параллельных буфера : один с тегами, другой без. Мы будем использовать второй для сравнения с деталями, а первый-для генерации выходных данных.

 const sentence = `[t1]Sometimes[/t1] that's [t2]just the way[/t2] it has to be. Sure, there were [t3]probably[/t3] other options, but he didn't let them [t4]enter his mind[/t4]. It was done and that was that. It was just the way [t5]it[/t5] had to be.`


const parts = [
  "Sometimes that's just the way",
  "it has to be.",
  "Sure,",
  "there were probably other options,",
  "but he didn't let them enter his mind.",
  "It was done and that was that.",
  "It was just the way it had to be."
];

let bufferWithoutTags = ""
let bufferWithTags = ""
const output = []
const buffers = []
let tagOpened = false

for (let i = 0; i < sentence.length;   i) {
  let c = sentence[i]
  bufferWithTags  = c
  if ( c === '[') {
    if (tagOpened amp;amp; sentence[i 1] === "/") {
      tagOpened = false
    } else {
      tagOpened = true
    }
    while (c != ']') {
      c = sentence[  i]
      bufferWithTags  = c
    }
  } else {
    bufferWithoutTags  = c;
  }
  if (!tagOpened) {
    for (const part of parts) {
      if (part === bufferWithoutTags.trim()) {
        output.push(bufferWithTags.trim())
        bufferWithTags = bufferWithoutTags = ""
      }
    }
  }
}
console.log(output)
 

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

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