Регулярное выражение для получения атрибутов из HTML-комментария в виде строки

#javascript #regex #regex-group

#javascript #регулярное выражение #регулярное выражение-группа

Вопрос:

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

  1. <!--Tag:Name-->
  2. <!--Tag:Name param="abc"-->
  3. <!--Tag:Name param="abc" param2="xyz"-->

Кроме того, у меня есть файл со многими из этих тегов, поэтому я хочу сначала найти все теги, а затем проанализировать каждый по одному

пример файла

 <head>
   <!--Tag:Test-->
   <!--Tag:Test2 param="abc"-->
   <!--Tag:Test3 param2="abc" param5="xyz"-->
</head>
 

Я ищу регулярное выражение для анализа такого рода скриптов и в соответствии получаю имя и атрибуты

Я пробовал что-то вроде

 tempRegex = new RegExp(/<!--Tag:(.*?)s{1,}(.*?=".*?")-->/, 'i');

`<!--Tag:Test param="abc" param2="xyz"-->`.match(tempRegex);
 

Но он возвращает совпадающие группы:

 0: "<!--Tag:Test param="abc" param2="xyz"-->"
1: "Test"
2: "param="abc" param2="xyz""
 

Чего я хочу добиться, так это

 0: "<!--Tag:Test param="abc" param2="xyz"-->"
1: "Test"
2: param="abc" 
3: param2="xyz"
 

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

1. Вы указали, что он делает. Проблема не в этом.

2. Кроме того, есть ли причина, по которой это должно быть комментарием? <template tag="Name" param="abc" param2="xyz"></template> было бы намного проще обрабатывать с существующей собственной логикой

Ответ №1:

Вы хотите извлечь что-то вроде «ключ — значение»?

 ((w )[:=]"*(w )"*)
 

Это было бы:

 Tag:Test
param="abc"
param2="xyz"
 

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

1. Да, я хочу извлечь в массив, который выглядит как [Имя тега, первая пара, вторая пара и т. Д.]

2. Это приведет к сбою для чего-то вроде <!--Tag:Name param="a:bc"-->

Ответ №2:

Это сделало бы это:

 /Tag:[a-z] |[a-zd] ="[^"] "/gmi
 

https://regex101.com/r/6dVJXO/1

 var s = `<!--Tag:Name param="abc" param2="xyz"-->`;
var r = /Tag:[a-z] |[a-zd] ="[^"] "/gmi;
console.log([...s.matchAll(r)]); 

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

1. выглядит красиво, но также соответствует <Tag:Name param="abc" param2="xyz"> , кроме того, я бы предпочел не глобальное регулярное выражение, если это возможно, потому что сначала мне нужно получить все эти совпадающие теги из файла, а затем проанализировать каждый по одному

2. @goq123 Я вижу, что вы обновили свой вопрос, чтобы выявить новые требования, поэтому первым шагом будет запуск /<!--.[sS]*?-->/g ( regex101.com/r/vhl4Ln/1 ) для всей строки выполните цикл совпадений и запустите регулярное выражение, которое я указал в ответе, для каждого совпадения.

3. @goq123 Кроме того, в вашем вопросе указано, что вы можете комментировать блоки, так что случилось <Tag:Name param="abc" param2="xyz"> ??

4. у меня есть строгое правило, которое я сопоставляю только <!--Tag:name--> с параметрами или без них, меня интересует только эта форма подписи

5. @goq123 Для дальнейшего использования сделайте свой вопрос как можно более полным. Вы можете легко объединить все, что я вам показал, во что-то, что работает для вас.

Ответ №3:

Вы можете ознакомиться с исходным кодом по адресу https://github.com/artdecocode/rexml это вроде как делает то, что вы хотите, но вам нужно знать название тегов в advanced, но вы можете изменить регулярное выражение.

 /**
 * Extract member elements from an XML string. Numbers and booleans will be parsed into their JS types.
 * @param {string|!Array<string>} tag Which tag to extract, e.g., `div`. Can also pass an array of tags, in which case the name of the tag will also be returned.
 * @param {string} string The XML string.
 * @example
 *
 * const xml = `
 * <html>
 *   <div id="1" class="test" contenteditable>
 *     Hello World
 *   </div>
 * </html>
 * `
 * const [{ content, props }] = extractTag('div', xml)
 * // content: Hello World
 * // props: { id: 1, class: 'test', contenteditable: true }
 */
const extractTags = (tag, string) => {
  const tags = Array.isArray(tag) ? tag : [tag]
  const t = tags.join('|')
  const end1 = /s*/>/
  const end2 = />([sS] ?)?</1>/
  const re = new RegExp(`<(${t})${simple.source}?(?:${end1.source}|${end2.source})`, 'g')

  const matches = mismatch(re, string, ['t', 'a', 'v', 'v1', 'v2', 'c'])
  const res = matches.map(({ 't': tagName, 'a': attributes = '', 'c': content = '' }) => {
    const attrs = attributes.replace(//$/, '').trim()
    const props = extractProps(attrs)
    return { content, props, tag: tagName }
  })
  return res
}