Соответствовать
condition #1.The last occurrence of a string of characters followed by a comma or white space.
condition #2.The occurrence has to be the end of the string
condition #3.The occurrence has to be a unique sub-string
Я не могу понять, как применить третье условие к моему регулярному выражению.
Выражение:
/[\w]{2,30}[\s,](?!.*[\w]{2,30}[\s,])$/g
[\w]{2,30} --Any sub-string of characters of length 2 to 30
[\s,] --Is white space or comma
(?!.*[\w]{2,30}[\s,]) --Only match the last occurrence
$ --End of string
Мое выражение охватывает только условия №1 и №2.
#1. The last occurrence of a string of characters followed by a comma or white space.
#2. The occurrence has to be the end of the string.
Я хочу, чтобы мое выражение возвращало совпадение, когда [\w]{2,30} является уникальным И #1 #2 все еще действительны.
//Result
string: 'a, bb, ccc, ccc(space or ,)'
match: 'ccc(space or ,)'
//Expected Results
string: 'a, bb, ccc, ccc(space or ,)'
match: no match
string: 'a, bb, ccc, ccc(space), abc(space or ,)'
match: 'abc(space or ,)'
string: 'a, bb, ccc, ccc(space), abc(space or ,)(any character or white space or ,)'
match: no match
Чтобы применить третье условие совпадения уникальной подстроки, вы можете использовать положительный просмотр вперед, чтобы убедиться, что подстрока не повторяется ранее в строке. Вот обновленное регулярное выражение, включающее все три условия:
/(?<=\s|^)[\w]{2,30}\s,/g
Давайте разберем это:
(?<=\s|^) — Положительный просмотр назад, чтобы гарантировать, что совпадению предшествует пробел или начало строки.
[\w]{2,30} — любая подстрока символов длиной от 2 до 30.
[\s,] - пробел или запятая.
(?=(?:(?!\1)[\w]{2,30}[\s,])*[\w]{2,30}[\s,]$) - Положительный просмотр вперед, чтобы гарантировать, что подстрока не повторяется ранее в строке и является последним вхождением.
Это достигается с помощью незахватывающей группы (?:) с отрицательным опережением для проверки любого предыдущего вхождения той же подстроки, за которой следует та же подстрока в конце строки.
Обратите внимание, что использование \1 в отрицательном прогнозе относится к предыдущей захваченной группе, которая в данном случае является подстрокой символов, соответствующей предыдущему экземпляру [\w]{2,30}[\s,].
(?<=\s|^)[\w]{2,30}[\s,] возвращает несколько совпадений. regex101.com/r/F2B4TP/1. Должно быть только одно совпадение, и оно должно быть в конце строки.
Вы можете попробовать:
\b(\w{2,30})(?<!\b\1\b.*?\b\1\b)[ ,]$
Посмотреть онлайн демо
\b(\w{2,30})
- граница слова, за которой следует группа захвата, соответствующая подстроке из 2-30 символов слова;(?<!\b\1\b.*?\b\1\b)
- Отрицательный просмотр назад (допускается нулевая ширина) для проверки ранее захваченной подстроки, которая ранее не была найдена;[ ,]$
- Пробел или запятая перед якорем конечной строки.const r1 = ['a, bb, ccc, ccc ', 'a, bb, ccc, ccc , abc ', 'a, bb, ccc, ccc , abc '];
const r2 = r1.map(Re_Extract);
function Re_Extract(str) {
const s = str.match(/\b(\w{2,30})(?<!\b\1\b.*?\b\1\b)[ ,]$/g);
if (s) {
return s[0];
}
else {
return s;
}
}
console.info(r2);
В своем шаблоне вы только сопоставляете, но не проверяете одно и то же вхождение шаблона \w{2,30}, чтобы убедиться, что он уникален.
Для этого вы можете использовать отрицательный просмотр вперед с группой захвата и обратной ссылкой, чтобы убедиться, что вхождение в конце не присутствует ранее в строке.
^(?!.*\b(\w{2,30})\b.*\1[,\s]$).*\b(\w{2,30}[,\s])$
Объяснение
^
Начало строки(?!
Отрицательный просмотр вперед, утверждение, что вправо не
.*\b(\w{2,30})\b
Сопоставьте всю строку, затем границу слова и захватите в группе 1 соответствие от 2 до 30 символов слова, за которыми следует граница слова..*\1
Сопоставьте всю строку, а затем обратную ссылку на группу захвата 1, чтобы сопоставить тот же текст.[,\s]$
Соответствует либо ,
, либо пробелу в конце строки)
Закрыть просмотр вперед.*
Соответствуйте всей линии\b(\w{2,30}[,\s])
Граница слова, сопоставьте от 2 до 30 символов слова, за которыми следует либо ,
, либо символ пробела.$
Конец строкиПосмотрите демоверсию regex101
const regex = /^(?!.*\b(\w{2,30})\b.*\1[,\s]$).*\b(\w{2,30}[,\s])$/;
[
"a, bb, ccc, ccc ",
"a, bb, ccc, ccc , abc ",
"a, bb, ccc, ccc , abc "
].forEach(s => {
console.info(`${regex.test(s)} ---> ${s}`);
})
Тай! Я считаю, что ваш ответ является наиболее полным, потому что он решил задачу, и вы дали более полное объяснение компонентов в своем выражении.
\1 возвращает ошибку. Вот ссылка regex101.com/r/3K0bkq/1