Шаблон регулярного выражения для разбиения строки БЭМ на части (PHP) - PullRequest
2 голосов
/ 13 июня 2019

Я бы хотел выделить части блока, элемента и модификатора строки с помощью регулярного выражения PHP.Аромат БЭМ, который я использую, строчный и дефисный.Например:

this-defines-a-block__this-defines-an-element--this-defines-a-modifier

Моя строка всегда форматируется, как указано выше, поэтому регулярному выражению не нужно отфильтровывать недопустимые БЭМ, например, у меня никогда не будет грязных строк, таких как:

This.defines-a-block__this-Defines-an-ELEMENT--090283

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

this-is-block-001__this-is-element-001--modifier-002

Наконец, модификатор является необязательным, поэтому не каждая строка будет иметь такой, например:

this-is-a-block-001__this-is-an-element
this-is-a-block-002__this-is-an-element--this-is-an-optional-modifier

Я ищу какое-нибудь регулярное выражение для возврата каждого раздела разметки БЭМ.Каждая строка будет изолирована и отправлена ​​регулярному выражению индивидуально, а не в виде группы или многострочных строк.Следующее отправлено индивидуально:

# String 1
block__element--modifier

# String 2
block-one__element-one--modifier-one

# String 3
block-one-big__element-one-big--modifier-one-big

# String 4
block-one-001__element-one-001

Вернется:

# String 1
block
element
modifier

# String 2
block-one
element-one
modifier-one

# String 3
block-one-big
element-one-big
modifier-one-big

# String 4
block-one-001
element-one-001

1 Ответ

3 голосов
/ 13 июня 2019

Вы можете использовать 3 группы захвата и сделать третью необязательной, используя ?

Поскольку все 3 группы являются строчными, могут содержать цифры и использовать дефис в качестве разделителя, вы можете использовать класс символов [a-z0-9].

Вы можете повторно использовать шаблон для группы 1, используя (?1)

\b([a-z0-9]+(?:-[a-z0-9]+)*)__((?1))(?:--((?1)))?\b

Объяснение

  • \b Граница слова
  • ( Первая группа захвата
    • [a-z0-9]+ Повторите 1+ раз то, что указано в классе персонажей
    • (?:-[a-z0-9]+)* Повторите 0+ раз, сопоставляя - и 1+ раз, что в классе персонажа
  • ) Закрыть группу 1
  • __ Совпадение буквально
  • ((?1)) Группа захвата 2, группа рекурсоров 1
  • (?: Группа без захвата
    • -- Совпадение буквально
    • ((?1)) Группа захвата 3, группа рекурсоров 1
  • )? Закрыть группу без захвата и сделать ее необязательной
  • \b Граница слова

Regex demo

Или используя именованные группы:

\b(?<block>[a-z0-9]+(?:-[a-z0-9]+)*)__(?<element>(?&block))(?:--(?<modifier>(?&block)))?\b

Regex demo

...