RegEx: поиск всех css -классов в строке (с интервалом (/ из)) - PullRequest
0 голосов
/ 10 апреля 2020

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

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

Вот примеры таких строк:

Need to match:

.class
.class-media.other-class__item:nth-child(n)
.class-media .class-media__title::before

Don't need to match:

sometext.url.domain

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

Пока я создаю это:

(^|\s)(\.)([a-zA-Z_-]{1}[\w-_]+)/g

, но это не так t позволяет захватывать классы без пробелов и не захватывать ".url.domain"

Вот пример для https://regex101.com/r/MWLjLa/1/

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

Ответы [ 2 ]

1 голос
/ 10 апреля 2020

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

\w+(?:\.\w+)+|(\.\w+(?:-\w+)*)

По частям

  • \w+(?:\.\w+)+ Чтобы предотвратить захват, сначала сопоставьте слово символы повторяются 1+ раз . и слово символы
  • | или
  • ( группа захвата 1
    • \.\w+ соответствует начальной точке, 1 + слово chars
    • (?:-\w+)* Повторить сопоставление -` и 1+ слово символов
  • )

Regex demo

const regex = /\w+(?:\.\w+)+|(\.\w+(?:-\w+)*)/g;
const str = `Match:

.class
.class-media.other-class__item:nth-child(n)
.class-media .class-media__title::before

Don't match:

sometext.url.domain
sometext.url.domain.test.test`;
let m;

while ((m = regex.exec(str)) !== null) {
  // This is necessary to avoid infinite loops with zero-width matches
  if (m.index === regex.lastIndex) {
    regex.lastIndex++;
  }
  if (undefined !== m[1]) console.log(m[1]);
}

Если вы хотите использовать спичку при замене:

const regex = /(\w+(?:\.\w+)+)|(\.\w+(?:-\w+)*)/g;
const str = `Match:

.class
.class-media.other-class__item:nth-child(n)
.class-media .class-media__title::before

Don't match:

sometext.url.domain
sometext.url.domain.test.test`;
let m;

let result = str.replace(regex, (_, g1, g2) => undefined !== g2 ? g2 + "mewmewmew" : g1);
console.log(result)
0 голосов
/ 10 апреля 2020

Надеюсь, я правильно понял вашу проблему:

Как насчет этого: ^(\.[\w-]+\s?)+/gm

См. Пример здесь: https://regex101.com/r/SslScl/1


Он должен начинаться с точки ^\., затем следует имя класса [\w-]+.

Поскольку в одной строке может быть больше классов, мы добавляем + после скобок -> ^(\.[\w-]+)+ поэтому он найдет .class1-xxx.class2-yyy.

Но между ними может быть (но не обязательно) пробел, поэтому мы добавляем \s?. Добавьте также многострочный поиск, и все готово:

^(\.[\w-]+\s?)+/gm


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

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